Tutorials Logic, IN info@tutorialslogic.com

Cannot read map of undefined in React Fix: Causes and Fixes

What is This Error?

This error is a data-shape problem. React renders before async data arrives, so a value that will eventually be an array may be undefined during the first render.

A detailed fix includes both initialization and UI states: initialize list state as [], show loading while the request runs, show an error when the request fails, and confirm the API response is actually an array before calling map.

Prevent React map-of-undefined failures by initializing list state consistently, validating API shapes, and rendering loading or error states before iteration.

The error "Cannot read properties of undefined (reading 'map')" is extremely common in React. It occurs when you try to call .map() on a variable that is undefined or null "" usually because async data hasn't loaded yet, or an API returned an unexpected shape.

Common Causes

  • State initialized as undefined instead of an empty array
  • API data not loaded yet when component first renders
  • API response has a different shape than expected
  • Prop not passed to component (undefined by default)
  • Accessing a nested property that doesn't exist

Quick Fix (TL;DR)

Immediate Fix: Undefined

Immediate Fix: Undefined
// Wrong Problem
const [users, setUsers] = useState(); // undefined!
return users.map(u => <p>{u.name}</p>); // Error!

// Correct Solution 1: Initialize with empty array
const [users, setUsers] = useState([]);

// Correct Solution 2: Optional chaining
return users?.map(u => <p>{u.name}</p>);

// Correct Solution 3: Fallback
return (users || []).map(u => <p>{u.name}</p>);

Common Scenarios & Solutions

Failure: Undefined

Failure: Undefined
function ProductList() {
  const [products, setProducts] = useState(); // Wrong undefined!

  useEffect(() => {
    fetch('/api/products')
      .then(r => r.json())
      .then(setProducts);
  }, []);

  return products.map(p => <div key={p.id}>{p.name}</div>); // Error on first render!
}

Correction: Empty array default

Correction: Empty array default
function ProductList() {
  const [products, setProducts] = useState([]); // Correct Empty array default
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/products')
      .then(r => r.json())
      .then(data => {
        setProducts(data);
        setLoading(false);
      });
  }, []);

  if (loading) return <p>Loading...</p>;
  return products.map(p => <div key={p.id}>{p.name}</div>);
}

Failure: API returns: { data: { users: [...] } }

Failure: API returns: { data: { users: [...] } }
// API returns: { data: { users: [...] } }
useEffect(() => {
  fetch('/api/users')
    .then(r => r.json())
    .then(setUsers); // Wrong Sets users to { data: { users: [...] } }
}, []);

return users.map(u => <p>{u.name}</p>); // Error! users is an object

Correction: Extract the array

Correction: Extract the array
useEffect(() => {
  fetch('/api/users')
    .then(r => r.json())
    .then(response => {
      setUsers(response.data.users); // Correct Extract the array
    });
}, []);

// Or with optional chaining as safety net
return (users ?? []).map(u => <p>{u.name}</p>);

Failure: Error if items not passed

Failure: Error if items not passed
function List({ items }) {
  return items.map(item => <li>{item}</li>); // Error if items not passed!
}

// Usage "" forgot to pass items
<List /> // items is undefined!

Correction: Default prop value

Correction: Default prop value
// Correct Default prop value
function List({ items = [] }) {
  return items.map(item => <li key={item}>{item}</li>);
}

// Correct Or with PropTypes
import PropTypes from 'prop-types';
List.defaultProps = { items: [] };
List.propTypes = { items: PropTypes.array };

Cannot Read Map Undefined Correction 4

Cannot Read Map Undefined Correction 4
function DataList() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('/api/data')
      .then(r => r.json())
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!data || !Array.isArray(data)) return <p>No data</p>;

  return (
    <ul>
      {data.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
}

Best Practices to Avoid This Error

  • Always initialize array state with [] - Never leave it as undefined
  • Use loading states - Show a spinner while data is being fetched
  • Validate API response shape - Log the response to verify its structure
  • Use default props - Provide fallback values for array props
  • Use optional chaining - data?.map() returns undefined instead of throwing
  • Check Array.isArray() - Verify data is actually an array before mapping
  • Handle errors gracefully - Show error messages when fetch fails

First Render and Async Data

React does not wait for useEffect before rendering the component. The first render uses the initial state. If the initial state is undefined and JSX calls users.map(...), JavaScript throws before React can show the intended list.

The simplest fix is to initialize the state with the same shape you plan to render. If the UI renders a list, start with an empty array. If the UI renders an object, start with null and guard the object before reading properties.

  • Use useState([]) for lists.
  • Use Array.isArray when API shape is uncertain.
  • Render loading and error states explicitly.
  • Do not call map on undefined, null, or an object.

API Response Shape Notes

Many APIs return an object that contains the array, such as { users: [...] } or { data: [...] }. If you store the whole object and then call response.map, the code fails because the object itself is not an array.

Inspect the response once, choose the exact array field, and store that field in state. This makes rendering simpler and prevents repeated optional chaining throughout the JSX.

  • Check whether the array is response, response.data, or response.users.
  • Store normalized data in state.
  • Keep fallback arrays for missing optional sections.
  • Avoid hiding bad API shapes silently in production code.

Fixing map errors by controlling the first render

Cannot read map of undefined usually appears when a React component renders before async data has arrived. The first render happens with the initial state, so if users is undefined and the JSX calls users.map(), JavaScript throws before React can show the list. The fix begins with choosing a safe initial value.

For list data, initialize state as an empty array when the UI expects an array. If the API shape is uncertain, verify it before storing it. Loading and empty states also make the component clearer: loading explains that data is still coming, empty explains that the request succeeded but there are no items.

  • Initialize list state with [] instead of undefined.
  • Check API response shape before calling setState.
  • Render loading and empty states separately.
  • Use Array.isArray when data may not be an array.

Wrong: users Starts as undefined

Wrong: users Starts as undefined
function UserList() {
  const [users, setUsers] = useState();

  return users.map(user => <p key={user.id}>{user.name}</p>);
}

Correct: Initialize and Render States

Correct: Initialize and Render States
function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("/api/users")
      .then(res => res.json())
      .then(data => setUsers(Array.isArray(data) ? data : data.users ?? []))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <p>Loading...</p>;

  return users.map(user => <p key={user.id}>{user.name}</p>);
}

Safe list rendering after async fetch

Safe list rendering after async fetch
function UsersList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => setUsers(Array.isArray(data) ? data : []))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <p>Loading...</p>;
  return users.map(user => <p key={user.id}>{user.name}</p>);
}
Before you move on

Cannot read map of undefined in React Fix: Causes and Fixes Mastery Check

5 checks
  • Initialize list state with an empty array.
  • Check whether API data is actually an array.
  • Add loading and error UI states.
  • Use stable keys when mapping.
  • Avoid mapping before data shape is known.

Try this next

React JS Cannot Read Map Undefined Repair Drills

0 of 2 completed

  1. Start list state with an empty array, then render loading, success, empty, and error states for a delayed request without calling map on unknown data. The initial value should satisfy the operations performed during the first render.
  2. Test valid items, a missing items property, and an object where an array is required, then surface a controlled data-contract error. Check Array.isArray at the API boundary instead of hiding malformed data with a blanket fallback.

React JS Questions Learners Ask

A fetch started in useEffect runs after the first render, so the first render uses whatever initial value you gave the state.

Start by checking the value you are mapping.

For .map(), both are non-arrays, so both fail. undefined usually means no value was assigned yet, while null usually means the code intentionally recorded "no value." That distinction matters for UI design. undefined may belong to a loading state, while null may mean the server returned nothing or the user cleared a selection. Do not treat every non-array as the same.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.