How to fix Cannot read properties of undefined (reading 'map') in React

ReactBEGINNERHIGHUpdated Dec 9, 2025· 206 views

This error occurs when you try to call the .map() method on a variable that is undefined, typically when rendering lists in React components. The issue happens because data hasn't loaded yet, a prop wasn't passed, or an API response is being used before it's fetched.

Quick fix

Fixes Cannot read properties of undefined (reading 'map')

function UsersList({ users }) {
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)} // ❌ Error if users is undefined
    </div>
  );
}
  1. Add a null/undefined check before calling .map()
  2. Use a default value for array props
  3. Initialize state with an empty array
  4. Add a loading state and conditional rendering
react — error
function UsersList({ users }) {
return (
<div>
{users.map(user => <p key={user.id}>{user.name}</p>)} // ❌ Error if users is undefined
</div>
);
}
Cannot read properties of undefined (reading 'map')

What this error means

This error occurs when JavaScript attempts to access the "map" property on a value that is undefined. In React, this almost always happens when rendering arrays conditionally—you're trying to map over data that hasn't been initialized, hasn't loaded yet, or wasn't provided. The error is fundamental: undefined is not an array and has no methods. When React tries to render something like `data.map(item => <div>{item}</div>)` and `data` is undefined, JavaScript throws this TypeError immediately. This is one of the most common React errors because data loading is asynchronous, and components often render before data arrives. The issue is particularly common when: - Fetching data from an API with useEffect - Receiving props that might be undefined - Destructuring objects that don't exist yet - Accessing nested properties on undefined objects - Using state that hasn't been initialized The fix always involves ensuring the data exists and is an array before calling .map() on it.

Typical symptoms

  • Error message shows "Cannot read properties of undefined (reading 'map')" in browser console
  • White screen of death or blank page when component renders
  • Error appears only on first load, then disappears after data loads
  • Component crashes when trying to render a list
  • Browser shows unhandled promise rejection if data fetch fails
  • Error occurs specifically at the line where .map() is called
  • Works fine in development but fails intermittently in production

Common causes

  1. Calling .map() on undefined data before it loads from an API
  2. Props not being passed to a component that expects an array
  3. Destructuring an undefined prop or object property
  4. Accessing nested properties without checking if parent exists
  5. State variable not initialized with a default value
  6. Async data fetch hasn't completed when component renders
  7. API response returns null or undefined instead of an array
  8. Forgetting to check array existence before mapping over it

How to fix "Cannot read properties of undefined (reading 'map')"

1Add a null/undefined check before calling .map()

The simplest fix is to check if the data exists before mapping:

Bad - No check:

javascript
function UsersList({ users }) {
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)} // ❌ Error if users is undefined
    </div>
  );
}

Good - Check before mapping:

javascript
function UsersList({ users }) {
  return (
    <div>
      {users && users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}

Or with optional chaining (ES2020):

javascript
function UsersList({ users }) {
  return (
    <div>
      {users?.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}
2Use a default value for array props

Set a default value in function parameters or with PropTypes to ensure an array is always provided:

Using default parameters:

javascript
function UsersList({ users = [] }) {
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}

Using PropTypes:

javascript
import PropTypes from 'prop-types';

function UsersList({ users }) {
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}

UsersList.propTypes = {
  users: PropTypes.array.isRequired // Enforces array type
};

UsersList.defaultProps = {
  users: [] // Default to empty array
};

With TypeScript:

typescript
interface UsersListProps {
  users: User[]; // Always an array
}

function UsersList({ users = [] }: UsersListProps) {
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}
3Initialize state with an empty array

When using useState for data, always initialize with an empty array instead of undefined:

Bad - Initializes to undefined:

javascript
function UsersList() {
  const [users, setUsers] = useState(); // undefined initially
  
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)} // ❌ Error
    </div>
  );
}

Good - Initializes to empty array:

javascript
function UsersList() {
  const [users, setUsers] = useState([]); // Empty array initially
  
  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)} // ✓ Safe
    </div>
  );
}
4Add a loading state and conditional rendering

When fetching data asynchronously, use a loading state to handle the time before data arrives:

Example with useEffect:

javascript
function UsersList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchUsers() {
      try {
        const response = await fetch('/api/users');
        const data = await response.json();
        setUsers(data); // Set array safely
        setLoading(false);
      } catch (err) {
        setError(err.message);
        setLoading(false);
      }
    }
    
    fetchUsers();
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}

With React Query (modern approach):

javascript
import { useQuery } from '@tanstack/react-query';

function UsersList() {
  const { data = [], isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: async () => {
      const response = await fetch('/api/users');
      return response.json();
    }
  });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading users</p>;

  return (
    <div>
      {data.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}
5Check for undefined nested properties

When accessing nested array properties, ensure all parent objects exist:

Bad - No nested checks:

javascript
function PostList({ response }) {
  return (
    <div>
      {response.data.posts.map(post => <p key={post.id}>{post.title}</p>)} // ❌ Error if response, data, or posts is undefined
    </div>
  );
}

Good - With optional chaining:

javascript
function PostList({ response }) {
  return (
    <div>
      {response?.data?.posts?.map(post => <p key={post.id}>{post.title}</p>)}
    </div>
  );
}

Or with explicit checks:

javascript
function PostList({ response }) {
  if (!response || !response.data || !response.data.posts) {
    return <p>No posts available</p>;
  }
  
  return (
    <div>
      {response.data.posts.map(post => <p key={post.id}>{post.title}</p>)}
    </div>
  );
}
6Verify API response structure

Check your API documentation and verify the response structure before using it:

javascript
function UsersList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('/api/users')
      .then(response => response.json())
      .then(data => {
        // Log the response to verify structure
        console.log('API response:', data);
        
        // Check if data is array or nested inside response object
        if (Array.isArray(data)) {
          setUsers(data);
        } else if (Array.isArray(data.users)) {
          setUsers(data.users); // Some APIs nest arrays
        } else if (data && data.results) {
          setUsers(data.results);
        } else {
          console.error('Unexpected API response structure');
          setUsers([]); // Fallback to empty array
        }
      })
      .catch(err => {
        console.error('Fetch error:', err);
        setUsers([]); // Fallback on error
      });
  }, []);

  return (
    <div>
      {users.map(user => <p key={user.id}>{user.name}</p>)}
    </div>
  );
}

Always verify with console.log() or browser DevTools to confirm the actual API response before assuming its structure.

7Use TypeScript for type safety

TypeScript can catch these errors at compile time instead of runtime:

typescript
interface User {
  id: number;
  name: string;
}

interface UsersListProps {
  users: User[]; // Explicitly types as array
}

function UsersList({ users }: UsersListProps) {
  // TypeScript guarantees users is User[] array, never undefined
  return (
    <div>
      {users.map(user => (
        <p key={user.id}>{user.name}</p>
      ))}
    </div>
  );
}

// Or with async data:
function UserListContainer() {
  const [users, setUsers] = useState<User[]>([]); // Explicit type
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchUsers()
      .then(data => {
        setUsers(data); // TypeScript checks data is User[]
        setLoading(false);
      })
      .catch(() => setLoading(false));
  }, []);

  if (loading) return <p>Loading...</p>;

  return <UsersList users={users} />; // Type-safe
}

TypeScript will prevent you from passing undefined, null, or wrong types to .map().

Advanced notes

Array vs Array-like Objects: The .map() method only exists on true JavaScript arrays. Array-like objects (NodeList, arguments object) won't have .map(). Always convert them to arrays first: Array.from(nodeList).map(...) or [...nodeList].map(...).

Falsy vs Undefined: In React, checking if (data) handles both undefined and null, but also false, 0, and empty strings. Be careful when the value might legitimately be 0 or false. Use explicit checks: if (data !== undefined && data !== null) or with optional chaining: data?.map(...).

Performance with Empty Arrays: Initializing state with an empty array has minimal performance impact. React will render once with the empty array, then again when data loads. If this causes flickering, use the loading state approach (Step 4) to show a loading indicator instead.

React Suspense (Experimental): In React 18+, you can use Suspense for cleaner async data handling, but this is still experimental. It requires a compatible data fetching library like Relay or using frameworks like Next.js.

Error Boundaries: If you want to handle this error globally, wrap components with an Error Boundary:

javascript
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log('Error caught:', error, info);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong</h1>;
    }
    return this.props.children;
  }
}

Custom Hooks for Data Fetching: Extract the loading/error/data logic into a custom hook to avoid repetition across components:

javascript
function useFetch<T>(url: string): { data: T[]; loading: boolean; error: Error | null } {
  const [data, setData] = useState<T[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    fetch(url)
      .then(r => r.json())
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [url]);

  return { data, loading, error };
}

Debugging Tip: If unsure about data shape, always log the response: console.log('data:', data, 'is array:', Array.isArray(data)). This immediately shows whether the problem is undefined, null, or wrong structure.

Frequently asked questions

What does "Cannot read properties of undefined (reading 'map')" mean?
This error occurs when JavaScript attempts to access the "map" property on a value that is undefined. In React, this almost always happens when rendering arrays conditionally—you're trying to map over data that hasn't been initialized, hasn't loaded yet, or wasn't provided. The error is fundamental: undefined is not an array and has no methods.
How do I fix "Cannot read properties of undefined (reading 'map')"?
This error occurs when you try to call the .map() method on a variable that is undefined, typically when rendering lists in React components. The issue happens because data hasn't loaded yet, a prop wasn't passed, or an API response is being used before it's fetched.
What causes "Cannot read properties of undefined (reading 'map')"?
Calling .map() on undefined data before it loads from an API Props not being passed to a component that expects an array Destructuring an undefined prop or object property
Is the "Cannot read properties of undefined (reading 'map')" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading