Search code examples
javascriptreactjserror-handlingasync-await

Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'map')" when rendering dynamic data


I am building a React application where I fetch a list of items from an API and display them in a list. The API request is asynchronous, and here's my component code:

import React, { useEffect, useState } from "react";

function App() {
  const [items, setItems] = useState();

  useEffect(() => {
    fetch("https://api.example.com/items")
      .then((response) => response.json())
      .then((data) => setItems(data))
      .catch((error) => console.error("Error fetching data:", error));
  }, []);

  return (
    <div>
      <h1>Item List</h1>
      <ul>
        {items.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

When I load the page, I get this error in the browser:

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

I expected the items to load and be displayed in a list, but the application crashes instead.

  1. I tried logging the items state and noticed it starts as undefined.
  2. I expected React to handle the state update after the API call, but it seems to break before the data is fetched.
  3. I attempted setting the initial state to null instead of undefined, but the same error occurred. How can I fix this issue and ensure the app doesn’t crash while fetching data asynchronously?

Solution

  • The issue occurs because items is undefined initially, and you’re trying to call .map() on it. You need to handle the initial loading state and render the list only when items is defined. Update your code like this:

    function App() {
      const [items, setItems] = useState([]);
    
      useEffect(() => {
        fetch("https://api.example.com/items")
          .then((response) => response.json())
          .then((data) => setItems(data))
          .catch((error) => console.error("Error fetching data:", error));
      }, []);
    
      return (
        <div>
          <h1>Item List</h1>
          <ul>
            {items.length > 0 ? (
              items.map((item) => <li key={item.id}>{item.name}</li>)
            ) : (
              <p>Loading...</p>
            )}
          </ul>
        </div>
      );
    }

    Here, the state items is initialized as an empty array, and a conditional check ensures the app doesn’t try to call .map() on undefined.