This error occurs when a React component tries to access a prop that is undefined, often due to asynchronous data loading, incorrect prop passing, or context binding issues in class components. The solution depends on whether you are using functional or class components.
When a React component receives undefined for a prop value, it means the data expected to be passed from a parent component is not available at render time. This commonly happens in several scenarios: asynchronous data that has not yet loaded, props not being passed correctly from parent to child, or in class components, issues with context binding where `this.props` is undefined. React follows a one-way data flow where props move down from parent to child components. When this flow is interrupted or data is not yet available, props can be undefined. In React 18, rendering undefined no longer throws a runtime error, but it can still cause unexpected behavior in your application when components try to access properties on undefined values. The root cause often lies in the timing of data availability - components render before async data arrives, or props are simply not being passed down the component tree correctly. Understanding whether you are dealing with timing issues, prop passing problems, or class component context issues is key to resolving this error.
For functional components, use JavaScript destructuring with default values to handle undefined props:
function ItemList({ items = [] }) {
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}For props that might be objects:
function UserProfile({ user = { name: 'Guest', email: '' } }) {
return <div>{user.name}</div>;
}This ensures that even if the prop is undefined, your component has a safe default to work with.
If props depend on asynchronous data, add loading states and conditional rendering:
function ParentComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchData().then(result => {
setData(result);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (!data) return <div>No data available</div>;
return <ChildComponent data={data} />;
}This prevents passing undefined props by waiting for data to load before rendering child components.
Check that you are actually passing the prop from the parent component:
// ❌ Wrong - prop not passed
<ChildComponent />
// ✅ Correct - prop passed
<ChildComponent items={myItems} />Verify prop names match between parent and child:
// Parent
<UserCard userData={user} />
// Child - must use same prop name
function UserCard({ userData }) {
// Not 'user', must be 'userData'
}If using class components, ensure methods are properly bound. Use arrow functions:
class MyComponent extends React.Component {
// ✅ Arrow function - automatically bound
handleClick = () => {
console.log(this.props.value);
}
render() {
return <button onClick={this.handleClick}>Click</button>;
}
}Or bind in the constructor:
class MyComponent extends React.Component {
constructor(props) {
super(props); // ✅ Must call super(props)
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this.props.value);
}
}When accessing nested properties that might be undefined, use optional chaining:
function UserProfile({ user }) {
// ❌ Throws error if user is undefined
return <div>{user.profile.name}</div>;
// ✅ Safely handles undefined
return <div>{user?.profile?.name ?? 'Unknown'}</div>;
}Or use conditional rendering:
function UserProfile({ user }) {
if (!user) return <div>No user data</div>;
return <div>{user.profile.name}</div>;
}When passing state as props, initialize with appropriate defaults instead of undefined:
// ❌ State starts as undefined
const [user, setUser] = useState();
// ✅ State starts with default object
const [user, setUser] = useState({ name: '', email: '' });
// ✅ Or null if that better represents "no data yet"
const [user, setUser] = useState(null);This gives child components a predictable value to work with from the start.
Use PropTypes to catch undefined props during development:
import PropTypes from 'prop-types';
function ItemList({ items }) {
return <ul>{items.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}
ItemList.propTypes = {
items: PropTypes.array.isRequired
};
ItemList.defaultProps = {
items: []
};Or use TypeScript for compile-time checking:
interface Props {
items: Array<{ id: string; name: string }>;
}
function ItemList({ items }: Props) {
// TypeScript enforces items is always defined
}In React 18 and later, components can render undefined without throwing a runtime error, which changed from previous versions where this would cause an error. However, this does not mean undefined props are safe - accessing properties on undefined values will still throw errors.
When using defaultProps in class components or functional components, note that the default value is only used if the prop is missing or explicitly passed as undefined. If you pass null, the default will not be applied. To handle cases where undefined is explicitly passed, you may need to check props.value !== undefined rather than relying solely on defaultProps.
For TypeScript users, use optional props (prop?: type) to indicate props that might be undefined, and use non-null assertion (prop!) or type guards carefully. The NonNullable<T> utility type can help ensure props are defined. Consider using strict null checks in your tsconfig.json.
When working with destructuring defaults, be aware that checking props.value === undefined (instead of just !props.value) allows you to specify falsy values like 0 or empty strings, as !props.value would incorrectly treat these as undefined.
For complex prop validation needs, consider using a runtime validation library like Zod or Yup in addition to TypeScript, especially when props come from external APIs or user input where type safety cannot be guaranteed at compile time.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite