How to Fix 'Cannot read properties of undefined (reading map)'
Symptom: white screen, one red line in the console
TypeError: Cannot read properties of undefined (reading 'map')
Nine times out of ten it points at your list rendering line:
{users.map((u) => <UserCard key={u.id} user={u} />)}
The page goes blank (React 18 unmounts the whole tree on uncaught render errors) and the console shows a component stack. The error is not about .map — it says users is undefined, and calling anything on undefined throws.
Root causes: the three usual suspects
| Cause | Typical scenario | Signature |
|---|---|---|
| Async data not arrived | Rendering data.list.map(...) before fetch resolves | Crashes on first render; data arriving later doesn't recover the white screen |
| Field name mismatch | API returns { code, data: [...] } but code reads res.list | Crashes forever; the real structure is visible in the Network panel |
| Parent object missing | user.address is undefined, so user.address.cities.map(...) throws | Data with optional/foreign-key related fields where some records lack them |
Step one: look at what the API actually returns
Don't guess. Copy the raw response body and paste it into the JSON Formatter — the hierarchy expands instantly and you can see exactly which field holds the list (data? data.list? a top-level array?). To test the endpoint itself (including CORS-blocked or plain-http targets), fire it from the API Tester — server-proxy mode by default, immune to browser CORS limits.
The most common surprise: the API returns { list: [...] } on success but { message: "..." } on error — list simply disappears. Code written only for the happy path explodes the moment an error response arrives.
Fixes, in order of preference
1. A safe initial value (default empty array)
const [users, setUsers] = useState([]); // not useState() or null
While data is in flight, users.map runs against an empty array and renders nothing — no crash, no white screen. The single cheapest, highest-value line you can change.
2. Optional chaining + empty-array default (uncertain paths)
{(data?.list ?? []).map(...)}
// or for nested fields
{(user?.address?.cities ?? []).map(...)}
?. short-circuits on undefined; ?? [] guarantees .map always has an array. Note: this is a guard, not a band-aid — if the field never exists, the real fix is correcting the field name, not stacking question marks.
3. Conditional rendering (when loading vs empty matter)
{loading ? <Skeleton /> : users.length === 0 ? <Empty /> : users.map(...)}
Best UX, most code. Worth it for list pages; overkill for small components.
4. ErrorBoundary as the last line of defense
In React 18 one crashing component blanks the page. Wrap fragile regions in an ErrorBoundary so a crash degrades to a fallback UI instead of killing everything. Frameworks ship one (Next.js error.tsx); roll-your-own setups should add it.
FAQ
Works locally, crashes in test — why?
Local mocks always return the full shape; the test environment's API returns an error shape on failure — the missing field triggers the crash. Make your mock deliberately return one error-shaped response and this class of bug surfaces during development.
Added ?. and the list is just empty?
The data truly isn't there. Back to the Network panel: did the request fire? What status? Does the body contain the field you read? Three questions, all answered in one place.
Why does TypeScript not catch this?
users: User[] only checks assignments — runtime API responses aren't validated. For real defense use type guards, or generate types from a real response with JSON to TypeScript — the generated type honestly reflects optionality like { list?: User[] }.
Is reading 'length' or reading '0' the same bug?
Yes. The text after reading is the property you accessed on undefined — the fix is always "find out why the left side is undefined, then guard or fix the field".
The checklist (bookmark this)
- Open the component stack, locate the exact
.mapline - Inspect the raw response (or paste into the JSON Formatter)
- Confirm the real list path matches the code
- Guard with
useState([])/?? []/ conditional rendering - Add an ErrorBoundary on list pages so crashes don't spread
Provided by ToolVault. Related tools: JSON Formatter, API Tester, JSON to TypeScript. See the homepage for more developer tools.
Related Tools
Related Articles
How to Convert JSON to Java Entity Class (with annotations and List nesting)
Got JSON API data and want the matching Java POJO? Learn JSON-to-Java type mapping and common annotations, and step-by-step how to generate serializable classes locally.
How to Convert JSON to Go struct (with json tags and nested types)
Have a JSON API response and want the matching Go struct? Learn the JSON-to-Go type mapping rules and step-by-step how to generate code with json tags locally.
Complete Guide to HTML to JSX Conversion for React Developers
Understand the key differences between HTML and JSX, master className, style objects, camelCase attributes, and quickly migrate HTML snippets into React projects.