How to Fetch Data in useEffect in React: Simple Guide
To fetch data in React, use the
useEffect hook to run the fetch call after the component mounts. Inside useEffect, define an async function to fetch data and update state with useState, then call that function. This ensures data loads once and updates the component when ready.Syntax
The useEffect hook runs side effects like data fetching after the component renders. You usually define an async function inside it to fetch data, then update state with useState. The empty dependency array [] means it runs only once after the first render.
useEffect(() => { ... }, []): Runs once after mount.- Inside, define async fetch function.
- Call fetch function to get data.
- Update state to trigger re-render with new data.
javascript
import React, { useState, useEffect } from 'react'; function Component() { const [data, setData] = useState(null); useEffect(() => { async function fetchData() { const response = await fetch('https://api.example.com/data'); const json = await response.json(); setData(json); } fetchData(); }, []); return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>; }
Example
This example fetches a list of users from a public API when the component loads. It shows "Loading..." while waiting, then displays the user names once data arrives.
javascript
import React, { useState, useEffect } from 'react'; export default function UserList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchUsers() { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await response.json(); setUsers(data); setLoading(false); } fetchUsers(); }, []); if (loading) return <p>Loading users...</p>; return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ); }
Output
<ul><li>Leanne Graham</li><li>Ervin Howell</li><li>Clementine Bauch</li><li>Patricia Lebsack</li><li>Chelsey Dietrich</li><li>Mrs. Dennis Schulist</li><li>Kurtis Weissnat</li><li>Nicholas Runolfsdottir V</li><li>Glenna Reichert</li><li>Clementina DuBuque</li></ul>
Common Pitfalls
Common mistakes when fetching data in useEffect include:
- Not using an async function inside
useEffect(you cannot make the main function async). - Forgetting the empty dependency array
[], causing infinite fetch loops. - Not handling loading or error states, which can confuse users.
- Not cleaning up or cancelling fetches in some cases (advanced).
javascript
import React, { useState, useEffect } from 'react'; // Wrong: making useEffect callback async directly function Wrong() { const [data, setData] = useState(null); useEffect(() => { // ❌ This is not allowed async function fetchData() { const response = await fetch('https://api.example.com/data'); const json = await response.json(); setData(json); } fetchData(); }, []); return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>; } // Right: define async function inside useEffect function Right() { const [data, setData] = useState(null); useEffect(() => { async function fetchData() { const response = await fetch('https://api.example.com/data'); const json = await response.json(); setData(json); } fetchData(); }, []); return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>; }
Quick Reference
- useEffect(() => { ... }, []): Run once after mount.
- Define async fetch function inside
useEffect. - Call fetch function immediately.
- Update state with
useStateto re-render. - Handle loading and error states for better UX.
Key Takeaways
Use an async function inside useEffect to fetch data after the component mounts.
Always include an empty dependency array [] to avoid repeated fetches.
Update state with useState to trigger re-render with fetched data.
Handle loading states to inform users while data loads.
Never make the useEffect callback function itself async.