useFetchLoading saved progress…

useFetch

Almost every screen loads data, and the boilerplate is always the same: three pieces of state (data, error, loading), an effect to kick off the request, and — the part people forget — a guard so that when the URL changes fast, a slow earlier response can't clobber a newer one. useFetch packages all of that: pass a URL, get back { data, error, loading } that refetches when the URL changes and ignores stale replies.

Implement useFetch(url, options). It fetches JSON and returns { data, error, loading }. It refetches whenever url changes, treats a non-2xx response as an error, and discards any response that arrives after the URL has moved on or the component has unmounted.

Signature

function useFetch(url, options) {
  // returns { data, error, loading }
}

Examples

function User({ id }) {
  const { data, error, loading } = useFetch(`/api/users/${id}`);
  if (loading) return <Spinner />;
  if (error) return <Error message={error.message} />;
  return <Profile user={data} />;
}
// Typing fast in a search box changes the url rapidly; only the
// response for the CURRENT url is allowed to set state.
const { data } = useFetch(`/search?q=${query}`);

Notes

  • Three states, one objectloading true while in flight; on success set data and clear error; on failure set error and clear data.
  • Non-2xx is an errorfetch only rejects on network failure, so check response.ok and throw for HTTP errors like 404/500.
  • Ignore stale responses — track whether the current request is still the active one (a flag flipped in the effect's cleanup); only apply a response if it is. This is the race-condition fix.
  • Refetch on url change — key the effect on url; a falsy url should do nothing.
Loading editor…