Solve - Cannot read property 'map' of undefined in React.js

avatar

Borislav Hadzhiev

Last updated: Oct 20, 2021

banner

Check out my new book

Solve - Cannot read property 'map' of undefined #

The "cannot read property 'map' of undefined" error occurs when we call the map() method on an undefined value, most often when the map method is called before the data from an API request has arrived. To solve the error, initialize the value you're mapping over to an empty array.

cannot read property map of undefined

Here is an example of how the error occurs.

App.js
import {useState, useEffect} from 'react'; function App() { // ⛔️ State is not initialized to an empty array const [users, setUsers] = useState(); useEffect(() => { async function getUsers() { const response = await fetch('https://randomuser.me/api/', { method: 'GET', headers: { accept: 'application/json', }, }); const data = await response.json(); setUsers(data.results); } getUsers(); }, []); console.log(users); return ( <div> {/* ⛔️ users is `undefined` because API has not responded yet */} {users.map(user => ( <div key={user.id.value}> <h2> Name: {user.name.first} {user.name.last} </h2> </div> ))} </div> ); } export default App;

We declared the users variable, but did not initialize it to an empty array.

When the App function is called it tries to call the Array.map method on an undefined value and we get the error back.

To solve the error, initialize the value for the users variable to an empty array.

App.js
import {useState, useEffect} from 'react'; function App() { // ✅ State is initialized to an empty array const [users, setUsers] = useState([]); useEffect(() => { async function getUsers() { const response = await fetch('https://randomuser.me/api/', { method: 'GET', headers: { accept: 'application/json', }, }); const data = await response.json(); setUsers(data.results); } getUsers(); }, []); console.log(users); return ( <div> {/* ✅ users is initially [] and then gets populated after API responds */} {users.map(user => ( <div key={user.id.value}> <h2> Name: {user.name.first} {user.name.last} </h2> </div> ))} </div> ); } export default App;

We provided an empty array as the initial value in our call to the useState method.

This way, the users variable is initially set to an empty array and the map method is called on an empty array instead of an undefined value.

After our useEffect hook is ran and the remote API responds with the data, we update the state and our component rerenders.

At no point in time of the component's lifecycle is our users variable equal to undefined and the error won't occur.

The same would apply if you're using class components - you would still have to initialize the specific property on the state to an empty array before the data is fetched from the remote API.

If the error persists, console.log the value you are calling the map method on and make sure it is an array.

If your API response is empty, you might be setting your state to an undefined value, which can be a cause for the error.

You can also conditionally check if the variable is an array before calling the map() method, which would prevent you from getting the error.

App.js
import {useState, useEffect} from 'react'; function App() { const [users, setUsers] = useState([]); useEffect(() => { async function getUsers() { const response = await fetch('https://randomuser.me/api/', { method: 'GET', headers: { accept: 'application/json', }, }); const data = await response.json(); setUsers(data.results); } getUsers(); }, []); console.log(users); return ( <div> {/* ✅ check if array before calling `map()` */} {Array.isArray(users) ? users.map(user => ( <div key={user.id.value}> <h2> Name: {user.name.first} {user.name.last} </h2> </div> )) : null} </div> ); } export default App;

We used a ternary operator, which is very similar to an if/else statement.

We check if the users variable stores an array, and if it does we return the result of calling the map() method, otherwise we return null.

Another common cause of the error is trying to call the Map method on an array-like object, e.g. a Set.

index.js
function App() { const users = new Set(['James', 'Jon', 'Jan']); return ( <div> {/* ✅ check if array before calling `map()` */} {Array.from(users).map(user => ( <div key={user}>{user}</div> ))} </div> ); } export default App;

Had we tried to call the map() method directly on the Set object, we would get an error, so we had to convert the Set to an array using the Array.from method before calling map().

This would also be the case when working with other array-like objects like a NodeList.

Use the search field on my Home Page to filter through my more than 3,000 articles.