Tutorials Logic, IN info@tutorialslogic.com

Cannot read map of undefined in React Fix: Causes, Fixes, Examples & Interview Tips

What is This Error?

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)

Quick Solution

Quick Solution
// ❌ Problem
const [users, setUsers] = useState(); // undefined!
return users.map(u => <p>{u.name}</p>); // Error!

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

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

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

Common Scenarios & Solutions

Problem

Problem
function ProductList() {
  const [products, setProducts] = useState(); // ❌ 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!
}

Solution

Solution
function ProductList() {
  const [products, setProducts] = useState([]); // ✅ 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>);
}

Problem

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

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

Solution

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

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

Problem

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

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

Solution

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

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

Solution

Solution
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

Related Errors

Frequently Asked Questions

Because data fetched in useEffect isn't available on the first render. The component renders once with the initial state (undefined if not set), then useEffect runs and fetches data, triggering a second render with the actual data.

Initialize your state as an empty array: useState([]). Add a loading state to show a spinner while data loads. Use optional chaining: data?.map() as a safety net.

Both cause the same error. undefined is the default when no value is assigned. null is explicitly set to "no value". Both need to be handled before calling .map().

Use a try/catch block or .catch() in your fetch chain. Store the error in state and show an error message. Always check if data exists and is an array before mapping.

Yes! data?.map(item => ...) returns undefined if data is null/undefined instead of throwing an error. You can also use (data ?? []).map() to fall back to an empty array.

Ready to Level Up Your Skills?

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