Cannot Read Properties of Undefined
(Reading 'map') — Complete Fix
React 19 • Next.js 15 • TypeScript • Vite • React Router • Redux Toolkit
🧩 What Does “Cannot Read Properties of Undefined (Reading 'map')” Mean?
The “Cannot read properties of undefined (reading 'map')”
error is one of the most common runtime errors in React and JavaScript. It
occurs when you try to call the .map() method on a variable that
is undefined or null.
The full error message reads:
TypeError: Cannot read properties of undefined (reading 'map')
Why does this happen? React components often rely on data from
APIs, Redux stores, or parent props. If that data isn't available when the
component first renders (e.g., initial state is null), calling
.map() on it will throw this error.
⚡ Quick Reference — Common Causes at a Glance
null instead of an empty array [].{ ... }, not an array [ ... ].null.undefined as a prop to the child rendering the list.📋 Golden Rules to Avoid .map() Crashes
-
Initialize arrays with
[]— Never initialize state that holds a list withnullorundefined. -
Use optional chaining (
?.) —data?.items?.map()safely returnsundefinedinstead of crashing. -
Provide default fallbacks — Use the nullish coalescing operator:
data?.items ?? []. -
Handle loading states — Don't render the list until
datais truthy and is an array. -
Validate data shape — Use
Array.isArray(data)before calling.map(). - Use TypeScript — Define interfaces to catch missing or incorrect data shapes at compile time.
🧩 Detailed Breakdown — Every Scenario Solved
Each card below dives deep into one specific cause of the "Cannot read properties of undefined (reading 'map')" error, with root causes, code examples, and step-by-step fixes.
🛡️ Prevention — Avoid .map() Crashes Forever
For any state that will hold a list, use
useState([]) instead of
useState(null) or useState(undefined).
const items = data?.items ?? []; ensures you always have an array to map over.
Show a loading spinner or skeleton while data is being fetched. Only render the list when
data is available.
Define interfaces for your API responses and Redux state. TypeScript will catch missing properties at compile time.
Use
Array.isArray(data) before mapping. If the data is not an array, log an error or show a fallback.
async/await
and handle errors gracefully with try/catch. Return early if data is missing.
❓ Frequently Asked Questions
The error happens because the API response is not yet available
when the component first renders. The initial state is null or
undefined, and you're trying to call .map() on it.
Even if the API eventually returns an array, the component renders once with the initial state before the data arrives, causing the error.
[]
or use optional chaining data?.map().
Yes. Optional chaining (?. ) and nullish coalescing
(??) are supported in all modern browsers (Chrome 80+, Firefox 74+,
Safari 13.1+, Edge 80+). If you need to support older browsers, make sure your
build tool (Babel, Vite, Next.js) transpiles these features.
In Next.js 15 and Vite, these features are supported out of the box with modern JavaScript configurations.
.map() errors are handled?
No. React 19 doesn't change runtime behavior for standard
JavaScript methods like .map(). The error handling remains the
same as React 18.
However, React 19's new use hook for promises can make async
data fetching more ergonomic, but you still need to handle the case where
the data hasn't loaded yet.
Common Redux Toolkit causes:
- Initial state is
nullinstead of[]. - The selector returns
undefinedbecause the state slice doesn't exist yet. - API response shape doesn't match the expected array.
Debugging tips:
// ✅ Check your initial state in the slice
const initialState = {
items: [], // ✅ Not null!
};
// ✅ Use safe selectors
const selectItems = (state) => state.items ?? [];
// ✅ In your component
const items = useSelector(selectItems);
return <div>{items.map(item => ...)}</div>;
In Next.js 15 server components, you fetch data directly with async/await.
The error can still happen if you try to render data before it's fetched.
// ❌ Wrong — no error handling
async function Page() {
const data = await fetchData();
return <div>{data.items.map(...)}</div>; // 💥 If data is null
}
// ✅ Correct — with error handling
async function Page() {
const data = await fetchData();
if (!data?.items) {
return <p>No items found.</p>;
}
return <div>{data.items.map(...)}</div>;
}
useState or useEffect. Handle data validation
directly in the component logic.
Array.isArray() before mapping?
Yes, it's a great practice. Array.isArray()
is the most reliable way to check if a value is an array.
// ✅ Safe mapping with Array.isArray
function ItemList({ items }) {
if (!Array.isArray(items)) {
return <p>No items available.</p>;
}
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
This is especially useful when you're not sure about the data shape, such as when dealing with API responses or user input.
0 Comments
thanks for your comments!