This error occurs when your React code tries to access a property or method on a value that is undefined, commonly from destructuring undefined state, accessing nested object properties without null checks, or not waiting for async data. Fix it by adding null checks, optional chaining, or default values.
This error happens when JavaScript attempts to read a property from a value that is undefined. In React, this frequently occurs when accessing properties on state or props before they have been initialized, reading nested properties without checking if parent objects exist, destructuring values that might be undefined, or trying to use data before async operations complete. When React renders your component, if the data needed to display content is not yet available (still loading from an API, for example), the component may try to access properties on undefined objects. This breaks the component and causes a runtime error that crashes your application. The key insight is that undefined is not a valid object in JavaScript - it has no properties or methods. Whenever you access a property (using dot notation or bracket notation), you must first ensure the object itself exists. This is a common challenge in React because components often need to handle multiple data states: loading, error, and success states.
Before accessing any property, verify the object exists:
function UserCard({ user }) {
// Will crash if user is undefined
return <div>{user.name}</div>;
// Check first
if (!user) return <div>Loading...</div>;
return <div>{user.name}</div>;
// Or use conditional rendering
return user ? <div>{user.name}</div> : <div>No user</div>;
}For nested properties:
// Will crash if user or user.profile is undefined
return <img src={user.profile.avatar} />;
// Check each level
if (user && user.profile && user.profile.avatar) {
return <img src={user.profile.avatar} />;
}The optional chaining operator automatically checks if each level exists:
function UserCard({ user }) {
// Returns undefined instead of crashing if user or profile is undefined
const avatar = user?.profile?.avatar;
return <img src={avatar} />;
}Combine with nullish coalescing (??) for defaults:
function UserCard({ user }) {
// Returns email or default if user/email undefined
const email = user?.email ?? "[email protected]";
// Safe method calls
const displayName = user?.getName?.();
// Safe array access
const firstTag = user?.tags?.[0] ?? "untagged";
return <div>{displayName} ({email}) - {firstTag}</div>;
}Use default values in destructuring to handle undefined:
// data is undefined, accessing will crash
const { name, email } = undefined;
// Provide object default
const { name = "Guest", email = "none" } = user || {};
// Or check before destructuring
const { name, email } = user || { name: "Guest", email: "none" };For array destructuring:
// Will crash if items is undefined
const [first, ...rest] = items;
// Provide array default
const [first, ...rest] = items || [];Start state with values that will not cause crashes when accessed:
// State is undefined initially
const [user, setUser] = useState();
// Start with null (explicit no data)
const [user, setUser] = useState(null);
// Or start with default object structure
const [user, setUser] = useState({
name: '',
email: '',
profile: { avatar: null }
});
// Or start with empty array for lists
const [items, setItems] = useState([]);When setting state from async data:
useEffect(() => {
fetch("/api/user")
.then(res => res.json())
.then(data => setUser(data))
.catch(err => setUser(null));
}, []);Handle loading and error states explicitly:
function UserProfile() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchUser()
.then(data => {
setUser(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, []);
// Render different content based on state
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>No user data</div>;
// Only render user details if we reach here
return <div>{user.name} - {user.email}</div>;
}TypeScript helps prevent these errors before runtime:
interface User {
name: string;
email: string;
profile?: {
avatar?: string;
};
}
function UserCard({ user }: { user: User | undefined }) {
// TypeScript error: user might be undefined
// return <div>{user.name}</div>;
// TypeScript requires check or non-null assertion
if (!user) return null;
return <div>{user.name}</div>;
// Or use non-null assertion (!) if you are certain
return <div>{user!.name}</div>;
}Enable strict null checking in tsconfig.json:
{
"compilerOptions": {
"strictNullChecks": true,
"strict": true
}
}For data from external sources, validate the structure:
import { z } from "zod";
const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
profile: z.object({
avatar: z.string().url().nullable()
}).optional()
});
function fetchAndValidateUser(userId) {
return fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
const validated = UserSchema.safeParse(data);
if (!validated.success) {
console.error("Invalid user data", validated.error);
return null;
}
return validated.data;
});
}Arrays often cause this error when they are undefined:
function ItemList({ items }) {
// Crashes if items is undefined
return <ul>{items.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
// Use optional chaining
return (
<ul>
{items?.map(item => (
<li key={item.id}>{item?.name}</li>
))}
</ul>
);
// Or check first
if (!items || items.length === 0) {
return <div>No items to display</div>;
}
return <ul>{items.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}Optional chaining (.) is supported in all modern browsers and Node.js 14+. However, if you need to support older browsers, you may need a transpiler like Babel.
When combining optional chaining with operators, understand that obj?.prop returns undefined (not null) if the chain breaks. The nullish coalescing operator (??) only triggers on null and undefined, not other falsy values like 0 or empty strings.
In React, consider using a state machine library like XState for complex async data flows, especially when handling multiple states (loading, error, success, idle). This makes handling undefined data more explicit and reduces runtime errors.
When working with third-party APIs, always validate the response structure on first use. APIs may change, return unexpected null values, or have different structures in error conditions. Runtime validation libraries like Zod, Yup, or io-ts provide confidence that data matches expected structure.
For deeply nested structures, consider using lodash get function which safely traverses nested paths. However, with optional chaining becoming standard, this is less necessary.
In custom hooks that deal with undefined data, document the contract clearly. Return consistent types - if a hook might return undefined, be explicit about it in the return type signature. This makes consuming code safer and requires developers to handle the undefined case.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React