The Exact Error
TypeError: Cannot read properties of undefined (reading 'map')
Or in older JavaScript:
TypeError: Cannot read property 'map' of undefined
TypeError: Cannot read property 'map' of null
Quick summary:
.map()is an Array method. You called it on a value that isundefinedornullinstead of an array. The data either hasn't loaded yet, the API returned an unexpected shape, or a default value is missing.
Why This Error Happens
.map() is only defined on arrays. When you write data.map(item => ...), JavaScript looks up the map property on data. If data is undefined or null, there is no map property.
Five common root causes:
1. Async timing ? React renders the component immediately but the fetch hasn't completed. Your initial state is null or undefined.
2. API shape mismatch ? You expect { items: [...] } but the API returns { data: { items: [...] } } (one level deeper).
3. API returns null on empty ? Some backends return null instead of [] when there are no results.
4. Wrong destructuring ? const { items } = response.data when response.data is undefined.
5. Race condition ? A re-render happens after data is cleared but before new data arrives.
Step-by-Step Diagnosis
Step 1 ? Add console.log just before the error
console.log('data value:', data);
console.log('data type:', typeof data);
console.log('is array:', Array.isArray(data));
data.map(item => item.name); // Error is on this line
Step 2 ? Check the Network tab in DevTools
Open DevTools ? Network tab ? find your API request ? Response tab. Compare the actual JSON to what your code expects.
Step 3 ? Check your initial state
// WRONG:
const [users, setUsers] = useState(null);
// RIGHT:
const [users, setUsers] = useState([]);
Solutions
Solution 1 ? Initialize state as an empty array
const [items, setItems] = useState([]);
Solution 2 ? Use optional chaining with a fallback
{(data?.items ?? []).map(item => (
<div key={item.id}>{item.name}</div>
))}
Solution 3 ? Normalize API response at fetch time
async function fetchUsers() {
const response = await fetch('/api/users');
const json = await response.json();
const users = Array.isArray(json) ? json
: Array.isArray(json?.users) ? json.users
: Array.isArray(json?.data) ? json.data
: [];
setUsers(users);
}
Solution 4 ? Guard with a loading state
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
if (loading) return <Spinner />;
return items.map(item => <ItemCard key={item.id} item={item} />);
Solution 5 ? TypeScript to catch at compile time
const [users, setUsers] = useState<User[]>([]);
users.map(u => u.name); // TypeScript knows users is always User[]
Quick Reference
| Symptom | Likely Cause | Fix |
|---|---|---|
| Error on first render only | Initial state is null/undefined | useState([]) |
| Error for some users, not others | Conditional data fetching | Guard with ?? [] |
| Works in dev, fails in prod | Different API response in prod | Log raw response |
| API returns null for empty results | Backend null vs empty array | Normalize: data?.items ?? [] |
Prevent This Error in the Future
1. Always initialize array state with [] ? never null or undefined.
2. Add a normalization layer between your API calls and state. All data entering your app should be validated and defaulted to safe values.
3. Use TypeScript with strict null checks (strictNullChecks: true).
Use ToolNinja to Debug Faster
When the actual API response doesn't match what your code expects, the JSON Formatter helps you quickly understand the structure. Paste the raw API response to see it formatted with proper indentation.