Fetch Data in React with useEffect
Load data on mount inside useEffect, storing the result in state and cleaning up to avoid setting state after unmount.
Also known as: React data fetching, useEffect fetch
intermediate
Run the request in useEffect with a dependency array, save the result with useState, and use an ignore flag in cleanup so a late response can't update an unmounted component.
What it is
In React you fetch data as a side effect: put the call in useEffect and store the outcome in useState. The dependency array controls when it re-runs — [] means once after mount, [id] re-runs when id changes.
Because a component can unmount (or the input can change) before the request finishes, use a local ignore flag set in the effect's cleanup function. If the effect re-runs or the component unmounts, ignore becomes true and the stale response is discarded, preventing a race condition and the classic warning about updating state on an unmounted component.
Worked example
import { useEffect, useState } from "react";
function Post({ id }) {
const [post, setPost] = useState(null);
useEffect(() => {
let ignore = false;
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((res) => res.json())
.then((data) => {
if (!ignore) setPost(data);
});
return () => {
ignore = true;
};
}, [id]);
if (!post) return <p>Loading…</p>;
return <h1>{post.title}</h1>;
}
Failure mode — when it misleads
Forgetting the ignore cleanup causes race conditions when id changes quickly: an earlier, slower response can overwrite a newer one. Omitting a value used inside the effect from the dependency array leads to stale data. For anything beyond trivial cases, a library like React Query or SWR handles caching, dedup and cancellation for you.
Related entries
Sources & further reading
- Fetching data with Effects (React docs) (article)