How to Handle API Response in React: Simple Fix and Best Practices
useEffect to fetch data asynchronously and useState to store the response. Use async/await inside useEffect and update state to trigger re-render with the fetched data.Why This Happens
Many beginners try to fetch API data directly inside the component body or forget to handle asynchronous calls properly. This causes errors like infinite loops or no data rendering because React re-renders before data arrives.
import React, { useState } from 'react'; function UserList() { const [users, setUsers] = useState([]); // Incorrect: fetch called directly in component body fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(data => setUsers(data)); return ( <ul> {users.map(user => <li key={user.id}>{user.name}</li>)} </ul> ); }
The Fix
Move the API call inside useEffect to run it only once after the component mounts. Use async/await inside useEffect to handle the promise cleanly. Update state with the fetched data to trigger a re-render.
import React, { useState, useEffect } from 'react'; function UserList() { const [users, setUsers] = useState([]); useEffect(() => { async function fetchUsers() { try { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await response.json(); setUsers(data); } catch (error) { console.error('Error fetching users:', error); } } fetchUsers(); }, []); // Empty dependency array means run once return ( <ul> {users.map(user => <li key={user.id}>{user.name}</li>)} </ul> ); }
Prevention
Always place side effects like API calls inside useEffect with proper dependency arrays to avoid infinite loops. Use async/await for clearer asynchronous code. Handle errors with try/catch to avoid silent failures. Use state hooks to store and render data safely.
Enable linting rules like react-hooks/exhaustive-deps to catch missing dependencies. Test API calls separately to ensure they return expected data.
Related Errors
Common issues:
Too many re-renders: caused by calling state setters directly in the component body.Cannot read property 'map' of undefined: happens if you try to render data before it is fetched or initialized.Unhandled promise rejection: occurs when fetch errors are not caught.
Fix these by using useEffect, initializing state properly, and adding error handling.