Optional chaining (?.) is a modern JavaScript feature used to safely access deeply nested object properties without causing runtime errors.
- If any value in the chain is
nullorundefined, it returnsundefinedinstead of throwing an error - It is widely used in React applications and API handling
- Introduced in ES2020
const user = null;
console.log(user.name);
// ❌ Error: Cannot read property 'name' of nullconst user = null;
console.log(user?.name);
// ✅ undefined (no error)object?.property // Property access
object?.[expression] // Bracket notation
function?.(arguments) // Function callconst user = {
name: "Sandhya",
address: {
city: "Delhi"
}
};
console.log(user?.address?.city);
// Output: Delhi
console.log(user?.contact?.phone);
// Output: undefinedBenefit: No error thrown even if contact doesn't exist
const user = null;
console.log(user?.name);
// Output: undefined
console.log(user?.address?.city);
// Output: undefinedBenefit: Safe way to handle nullable objects
const users = [
{ name: "Aman" },
{ name: "Riya" }
];
console.log(users?.[0]?.name);
// Output: Aman
console.log(users?.[5]?.name);
// Output: undefined (no error)Benefit: Check if array exists and has elements without errors
const user = {
greet() {
return "Hello!";
}
};
console.log(user?.greet?.());
// Output: Hello
const admin = {};
console.log(admin?.greet?.());
// Output: undefined (no error)Benefit: Check if method exists before calling it
const response = {
data: {
user: {
profile: {
username: "sandhya_dev"
}
}
}
};
console.log(response?.data?.user?.profile?.username);
// Output: sandhya_dev
// What if data doesn't exist?
console.log(response?.error?.message?.text);
// Output: undefined (no error)Use Case: Safely accessing deeply nested API response data
console.log(user && user.address && user.address.city);Disadvantages:
- Verbose and hard to read
- Repetitive code
- Error-prone
console.log(user?.address?.city);Advantages:
- ✅ Cleaner and shorter
- ✅ More readable
- ✅ Better maintainability
let result;
const user = null;
// Stops at null, doesn't evaluate further
result = user?.address?.city;
console.log(result); // undefinedBenefit: Prevents unnecessary evaluations and performance improvements
const user = {
name: "",
age: 0
};
// Return default if undefined/null (not if falsy)
console.log(user?.address?.city ?? "Unknown City");
// Output: Unknown City
console.log(user?.name ?? "Guest");
// Output: "" (empty string is not null/undefined)// Component receiving props
function UserProfile({ user }) {
return (
<div>
<h1>{user?.name ?? "Guest"}</h1>
<p>{user?.contact?.email ?? "No email"}</p>
<button onClick={user?.logout?.()}>Logout</button>
</div>
);
}| Browser | Support |
|---|---|
| Chrome | v80+ |
| Firefox | v74+ |
| Safari | v13.1+ |
| Edge | v80+ |
| Node.js | v14+ |
| Feature | Before (??) | After (?.) |
|---|---|---|
| Readability | Low | High |
| Error Handling | Manual (&&) | Automatic |
| Code Length | Long | Concise |
| Maintainability | Difficult | Easy |