21. Build a useFetch Hook — Data Fetching with Cleanup

medium

useFetch looks simple but the interview is really about the race condition: if url changes while a request is in flight, a slow earlier response can land after the newer one and overwrite it.

The two safeguards

  1. active flag — set false in cleanup; never setState after the effect has been torn down (also silences the stale-response and unmount cases).
  2. AbortController — actually cancels the in-flight request on url change or unmount, instead of just ignoring it.

Follow-ups interviewers push on

  • "Which fixes the race — the flag or the abort?" → the flag prevents the bad setState; abort saves the wasted work. Use both.
  • "Refetch / retry?" → expose a refetch that bumps a counter in the dependency array.
  • "Caching, dedupe, revalidation?" → this is why SWR and React Query exist; name them.

What to practice

Build it, then trigger the race: rapidly change url and confirm the final state matches the last request, not whichever resolved last.

More questions

index.js
import { useEffect, useState } from "react";

function useFetch(url) {
  // return { data, error, loading }
  // bonus: ignore stale responses and abort on url change / unmount
}

// Usage:
// const { data, error, loading } = useFetch(`/api/user/${id}`);

Tests

Test Code

Enter JavaScript that runs after your solution. It should return a value or a Promise.