Fixing 'TypeError: data.map is not a function' in React

beginner⚛️ React2026-06-05| React (any version), Node.js, Modern Web Browsers

Error Message

TypeError: data.map is not a function
#react#javascript#frontend#debugging#api

The Anatomy of a White ScreenWe’ve all been there. You’ve just written a clean list component, the browser refreshes, and instead of your data, you’re met with a blank white screen. You open the console to find the culprit: TypeError: data.map is not a function.

This happens because JavaScript’s .map() method exists exclusively on the Array prototype. If your variable is an object, a string, null, or undefined, the engine doesn't know what to do. In the React ecosystem, this usually points to a breakdown in how data flows from your state or an external API.

The Exact Error Message```

TypeError: data.map is not a function


## Why This HappensIn my experience, 90% of these crashes fall into one of three categories:
- **The Empty Start:** You initialized your state as `null` or left it blank, but your JSX tried to render it before the first API call finished.- **The Wrapper Object:** Your API returned a response like `{ "users": [1, 2, 3] }`, but you tried to map over the top-level object instead of the `users` array.- **The Single Result:** The backend sent back a single object instead of an array when only one item was found.## How to Fix It### 1. Initialize State CorrectlyReact components often render at least once before your `useEffect` hook even starts fetching data. If you initialize state as `undefined`, that first render will attempt to call `undefined.map()`, causing an immediate crash.
**The Problem:**

const [items, setItems] = useState(); // Defaults to undefined

return (

The Fix: Always default to an empty array []. This allows the first render to complete successfully, showing nothing until the data actually arrives.

const [items, setItems] = useState([]); // Safe and predictable

2. Use Optional ChainingIf you can't guarantee that your data will always be an array, the optional chaining operator (?.) is your best friend. It acts as a safety valve. If the variable is nullish, the expression short-circuits and returns undefined instead of throwing a tantrum.

return (
  <ul>
    {data?.map(user => (
      <li key={user.id}>{user.username}</li>
    ))}
  </ul>
);

3. Drill Into the API ResponseMany developers assume response.data is the array they need. However, modern APIs often wrap results in metadata. Imagine you expect 50 products, but the API sends { "count": 50, "products": [...] }. Mapping over the response itself will fail because the response is a JSON object.

The Fix: Inspect the data shape immediately after the fetch. Use a fallback to prevent state from becoming null.

useEffect(() => {
  axios.get('/api/products').then(res => {
    // Ensure we are setting the array, not the wrapper
    setProducts(res.data.products || []); 
  });
}, []);

4. Add a Defensive Type CheckWhen dealing with unpredictable legacy systems, sometimes you need a hard guard clause. Using Array.isArray() ensures your code only attempts to loop if the data is actually loopable.

if (!Array.isArray(data)) {
  return <p>Loading or invalid data format...</p>;
}

return data.map(item => <div>{item.title}</div>);

Verification StepsOnce you apply a fix, verify it with these steps:

  • Console Audit: Open Chrome DevTools (F12) and ensure the red error text is gone after a hard refresh.- React DevTools: Check the "Hooks" section for your component. Confirm that the state begins as an empty array [].- Network Throttling: Use the "Slow 3G" setting in the Network tab. This tests if your UI handles the "waiting period" before the array arrives without crashing.## Proactive Prevention- TypeScript: Define your state types strictly (e.g., useState<User[]>([])). This catches potential map errors during development rather than at runtime.- Prop Defaults: If a child component receives a list, use destructuring defaults: const List = ({ items = [] }) => { ... }.- Sanitize Data: Always treat external API data as untrusted. Map or filter it into the format you need before saving it to your local state.

Related Error Notes