React: Cannot Read Properties of Undefined (Reading State)
TypeError: Cannot read properties of undefined (reading 'map')
What causes this
You’re calling .map() (or accessing a property) on something that’s undefined. In React, this almost always happens because:
- State hasn’t been initialized with a proper default value
- Data from an API hasn’t loaded yet on the first render
- You’re accessing a nested property that doesn’t exist
- A prop wasn’t passed to the component
React renders immediately — it doesn’t wait for your data to load. If your initial state is undefined and you try to .map() over it, you crash.
Fix 1: Set a proper default value in useState
// ❌ No default — items is undefined on first render
const [items, setItems] = useState();
return items.map(i => <li>{i}</li>); // TypeError!
// ✅ Default to an empty array
const [items, setItems] = useState([]);
return items.map(i => <li>{i}</li>); // Works — renders nothing initially
Match the default to the shape of your data:
const [user, setUser] = useState(null); // object or null
const [items, setItems] = useState([]); // array
const [count, setCount] = useState(0); // number
const [text, setText] = useState(''); // string
Fix 2: Use optional chaining
When dealing with nested data that might not exist yet:
// ❌ Crashes if data or data.items is undefined
return data.items.map(i => <li>{i.name}</li>);
// ✅ Optional chaining — returns undefined instead of crashing
return data?.items?.map(i => <li key={i.id}>{i.name}</li>);
Fix 3: Add a loading state
Don’t try to render data that hasn’t loaded:
const [items, setItems] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/items')
.then(res => res.json())
.then(data => {
setItems(data);
setLoading(false);
});
}, []);
if (loading) return <p>Loading...</p>;
if (!items) return <p>No data found</p>;
return items.map(i => <li key={i.id}>{i.name}</li>);
Fix 4: Check your props
If the data comes from a parent component:
// ❌ Parent might not pass items
function ItemList({ items }) {
return items.map(i => <li>{i}</li>); // TypeError if items is undefined!
}
// ✅ Default parameter
function ItemList({ items = [] }) {
return items.map(i => <li>{i}</li>);
}
Fix 5: Guard against API response shape changes
APIs sometimes return unexpected shapes:
useEffect(() => {
fetch('/api/items')
.then(res => res.json())
.then(data => {
// ❌ Assumes data is always an array
setItems(data);
// ✅ Validate the shape
setItems(Array.isArray(data) ? data : []);
});
}, []);
Related resources
How to prevent it
- Always initialize
useStatewith a value that matches the expected type — never leave it empty - Use TypeScript — it catches these errors at compile time by enforcing types on state and props
- Add loading states for any data that comes from an API or async source
- Use optional chaining (
?.) when accessing nested properties - Default destructured props:
{ items = [] }instead of{ items }