पाठ 12 / 25

Fetching Data Without Race Conditions

Ignore stale responses.

Guard against out-of-order results

When fetching in an effect, responses can arrive out of order: request A starts, the user switches to B, B returns first, then A returns and overwrites the screen with stale data. Use a cleanup flag (let ignore = false; return () => { ignore = true; }) or an AbortController to discard stale responses. In real apps, prefer a data-fetching library (TanStack Query, SWR) or your framework's data loading, which handle caching, deduplication, retries and races for you.

Switching users before the first response arrives, run

I ran this with React 19.3 and react-dom 19.3 on Node.js 22, compiling JSX with esbuild 0.28. Browser-style examples use jsdom 29 as a fake DOM (imported from a small setup-dom.mjs file) and act() to apply updates. User 1's fake request takes 50 ms and user 2's 10 ms. Switching to user 2 before user 1 has loaded, then waiting for both, shows "Ravi": the late response for user 1 is ignored thanks to the cleanup flag.

import "./setup-dom.mjs";   // test setup: jsdom provides a browser-like DOM in Node
import { useState, useEffect, act } from "react";
import { createRoot } from "react-dom/client";

const fakeApi = id => new Promise(r => setTimeout(() => r({ id, name: id === 1 ? "Asha" : "Ravi" }), id === 1 ? 50 : 10));
function User({ id }) {
  const [user, setUser] = useState(null);
  useEffect(() => {
    let ignore = false;                       // guards against out-of-order responses
    setUser(null);
    fakeApi(id).then(u => { if (!ignore) setUser(u); });
    return () => { ignore = true; };
  }, [id]);
  return <p>{user ? user.name : "Loading..."}</p>;
}
const root = createRoot(document.getElementById("root"));
await act(() => root.render(<User id={1} />));
console.log(document.querySelector("p").textContent);
await act(() => root.render(<User id={2} />));          // switch before user 1 has loaded
await act(() => new Promise(r => setTimeout(r, 80)));    // let both requests finish
console.log(document.querySelector("p").textContent);

Output:

Loading...
Ravi

Use a data library for real apps

Caching, refetching and request deduplication are hard to get right by hand; libraries and frameworks solve them.

त्वरित जाँच: What problem does the ignore flag in a fetch effect solve?

  • Network errors
  • A slow, outdated response overwriting newer data
  • Slow rendering
  • Missing keys
Answer

A slow, outdated response overwriting newer data — Discard stale results.