Are you running into the frustrating “TypeError: Cannot Read Property ‘Map’ of Undefined” error in your React application? This error can be tricky to debug, but fear not – we’ve got you covered.

In this article, we’ll walk you through the common causes and solutions to help you fix this error. Whether you’re a seasoned React developer or just starting out, this guide will help you get your app back on track.

What Causes the “TypeError: Cannot Read Property ‘Map’ of Undefined” Error?

The “TypeError: Cannot Read Property ‘Map’ of Undefined” error typically occurs when you try to access a property or method of an undefined value in your React code.

In plain terms, the error occurs when you try to map over an undefined value, such as an array that has not been initialized or has not yet received data.

In the example below, you are getting todo items from JSON Placeholder data, but the map method is called before the data from an API request has arrived.

import { useState, useEffect } from 'react';

function App() {
  const [todos, setTodos] = useState();

  useEffect(() => {
    const getTodos = async () => {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/todos?_limit=5'
      );
      const data = await response.json();
      setTodos(data);
    };
    getTodos();
  }, []);

  console.log(todos);

  return (
    <div>
      {todos.map((todo) => (
        <div key={todo.id}>
          <h2>Item: {todo.title}</h2>
        </div>
      ))}
    </div>
  );
}

export default App;

The code above will throw the “TypeError: Cannot read properties of undefined (reading ‘map’)” error:

TypeError: Cannot read properties of undefined (reading 'map') error message
TypeError: Cannot read properties of undefined (reading ‘map’) error message

You need to look for a way to let React know that the todos state is an array even before the array gets populated, or you need to avoid the map method from running until the todos state variable gets its data from the API request.

3 Ways To Fix the “TypeError: Cannot Read Property ‘Map’ of Undefined” Error

Here are three ways to fix the “TypeError: Cannot Read Property ‘Map’ of Undefined” error in React:

  1. Initialize your state variable to an empty array
  2. Use comparison operators
  3. Use the optional chaining operator (?.)

Let’s explore each of these solutions and how they can help you resolve the error in your React code.

1. Initialize Your State Variable to an Empty Array

One of the direct solutions to the “TypeError: Cannot Read Property ‘Map’ of Undefined” error is to ensure that the array variable you’re trying to map over is defined.

You can initialize your state variable to an empty array by default, which will ensure that the variable always exists and doesn’t throw an error when you try to map over it.

For example, the following are two similar components, the first’s state variable is not initialized to an empty array, while the second is initialized:

// Before initializing your state variable to an empty array
function MyComponent() {
  const [myList, setMyList] = useState();
  
  return (
    <ul>
      {myList.map(item => <li>{item}</li>)}
    </ul>
  );
}

// After initializing your state variable to an empty array
function MyComponent() {
  const [myList, setMyList] = useState([]);

  return (
    <ul>
      {myList.map(item => <li>{item}</li>)}
    </ul>
  );
}

In the example above, myList state variable is initialized to an empty array by default using useState([]). This ensures that even if myList is undefined initially, it will always be an array and won’t throw the “TypeError: Cannot Read Property ‘Map’ of Undefined” error.

For the fetch example, you can also initialize the todos state variable to an empty array ([]):

import { useState, useEffect } from 'react';

function App() {
  // Initialize the state to an empty array of todos.
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    const getTodos = async () => {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/todos?_limit=5'
      );
      const data = await response.json();
      setTodos(data);
    };
    getTodos();
  }, []);

  console.log(todos);

  return (
    <div>
      {todos.map((todo) => (
        <div key={todo.id}>
          <h2>Item: {todo.title}</h2>
       </div>
      ))}
    </div>
  );
}

export default App;

2. Use Comparison Operators

Another solution is to use comparison operators to check whether the array variable is defined before mapping over it. You can use the ternary or logical AND (&&) operator to achieve this.

Here are examples of using the ternary operator:

function MyComponent() {
  const [myList, setMyList] = useState();

  return (
    <ul>
      {myList ? myList.map(item => <li>{item}</li>) : null}
    </ul>
  );
}

In this example, you are checking if the myList array variable is defined before attempting to map over it. If myList is undefined, the ternary operator returns null, and nothing is rendered. If myList is defined, the map function is called, and the list items are rendered.

This is similar to using the logical AND operator:

function MyComponent() {
  const [myList, setMyList] = useState();

  return (
    <ul>
      {myList && myList.map(item => <li>{item}</li>)}
    </ul>
  );
}

With the use of comparison operators like the ternary operator, you can handle loading, so something else is displayed on the screen while you lead data from the API:

import { useState, useEffect } from 'react';

function App() {
  const [todos, setTodos] = useState();

  useEffect(() => {
    const getTodos = async () => {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/todos?_limit=5'
      );
      const data = await response.json();
      setTodos(data);
    };
    getTodos();
  }, []);

  console.log(todos);

  return (
   <div>
      {todos ? (
        todos.map((todo) => (
          <div key={todo.id}>
            <h2>Item: {todo.title}</h2>
          </div>
        ))
      ) : (
        <h1>Loading...</h1>
      )}
    </div>
  );
}

export default App;

3. Use the Optional Chaining Operator (?.)

You can also use the optional chaining operator (?.) introduced in ES2020. This operator allows you to safely access properties or methods, such as the map method of an array, without throwing an error if the array is undefined.

Here’s an example of a functional component that uses the chaining operator to check myList state variable:

function MyComponent() {
  const [myList, setMyList] = useState();

  return (
    <div>
      {myList?.map((item) => (
        <p>{item}</p>
      ))}
    </div>
  );
}

In the example above, you’re using the optional chaining operator to access the myList array variable safely. If myList is undefined, nothing will be rendered. If myList is defined, the map method will be called, and the list items will be rendered.

Summary

The “TypeError: Cannot Read Property ‘Map’ of Undefined” error can occur in React when using the map method on an undefined or null value.

To fix this error, we discussed three solutions. However, using comparison operators is the most versatile solution because it can handle situations where your API might send an empty response or a null value.

Additionally, when unsure if the data you’ll receive will be an array, you can add some methods to check and convert the data type before calling the map method.

Check out Kinsta’s Application Hosting and spin up your next React project today!

Now it’s your turn: Have you ever encountered this issue? How did you solve it? Are there any other approaches you used that are not covered in this article? Let us know in the comments!