🔧 Error Fixes
· 2 min read
Last updated on

React: Cannot Read Properties of Undefined (Reading State)


TypeError: Cannot read properties of undefined (reading 'map')

What causes this

You’re calling .map() (or accessing a property) on something that’s undefined. In React, this almost always happens because:

  • State hasn’t been initialized with a proper default value
  • Data from an API hasn’t loaded yet on the first render
  • You’re accessing a nested property that doesn’t exist
  • A prop wasn’t passed to the component

React renders immediately — it doesn’t wait for your data to load. If your initial state is undefined and you try to .map() over it, you crash.

Fix 1: Set a proper default value in useState

// ❌ No default — items is undefined on first render
const [items, setItems] = useState();
return items.map(i => <li>{i}</li>);  // TypeError!

// ✅ Default to an empty array
const [items, setItems] = useState([]);
return items.map(i => <li>{i}</li>);  // Works — renders nothing initially

Match the default to the shape of your data:

const [user, setUser] = useState(null);      // object or null
const [items, setItems] = useState([]);       // array
const [count, setCount] = useState(0);        // number
const [text, setText] = useState('');          // string

Fix 2: Use optional chaining

When dealing with nested data that might not exist yet:

// ❌ Crashes if data or data.items is undefined
return data.items.map(i => <li>{i.name}</li>);

// ✅ Optional chaining — returns undefined instead of crashing
return data?.items?.map(i => <li key={i.id}>{i.name}</li>);

Fix 3: Add a loading state

Don’t try to render data that hasn’t loaded:

const [items, setItems] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
  fetch('/api/items')
    .then(res => res.json())
    .then(data => {
      setItems(data);
      setLoading(false);
    });
}, []);

if (loading) return <p>Loading...</p>;
if (!items) return <p>No data found</p>;

return items.map(i => <li key={i.id}>{i.name}</li>);

Fix 4: Check your props

If the data comes from a parent component:

// ❌ Parent might not pass items
function ItemList({ items }) {
  return items.map(i => <li>{i}</li>);  // TypeError if items is undefined!
}

// ✅ Default parameter
function ItemList({ items = [] }) {
  return items.map(i => <li>{i}</li>);
}

Fix 5: Guard against API response shape changes

APIs sometimes return unexpected shapes:

useEffect(() => {
  fetch('/api/items')
    .then(res => res.json())
    .then(data => {
      // ❌ Assumes data is always an array
      setItems(data);

      // ✅ Validate the shape
      setItems(Array.isArray(data) ? data : []);
    });
}, []);

How to prevent it

  • Always initialize useState with a value that matches the expected type — never leave it empty
  • Use TypeScript — it catches these errors at compile time by enforcing types on state and props
  • Add loading states for any data that comes from an API or async source
  • Use optional chaining (?.) when accessing nested properties
  • Default destructured props: { items = [] } instead of { items }
📘