React Forum
Blog & Guide Responses
Sep 10, 2022 · 04:00 AM

MDN Fetch API - discussion (2022-09-10)

Started by Avery Chen
externalmdnfetchaborttimeoutscaching

We’re trying to keep our network layer “just fetch” without sliding into either a magic wrapper or a thousand one-off request shapes.

Read the docs

What’s your baseline contract for fetch in app code (timeouts, abort, retries, credentials)? Do you centralize that contract in one helper, or keep it close to each route/shell? How do you make fetch behavior explainable from the UI (signals, keys, posture) without dumping logs everywhere?

Comments (10)

Back to latest
Maya Henson
Sep 10, 2022 · 04:06 AM

AbortController everywhere. Anything without abort becomes “it hung” tickets.

Dmitri Kline
Sep 10, 2022 · 04:14 AM

I like a boring helper, but the key is making the resolved posture visible.

We render a small data-fetch marker in the route shell with { key, lane, timeoutMs, ok } so support can triage without reading wrapper code.

Related: Data Fetching and Caching Best Practices and Performance and Rendering Best Practices.

Salma Qureshi
Sep 10, 2022 · 04:22 AM

Minimal helper we use to keep abort + timeout consistent (and keep the surface honest):

ts
type FetchPosture = { timeoutMs: number; credentials?: RequestCredentials };

export async function fetchJson<T>(url: string, posture: FetchPosture, init?: RequestInit): Promise<T> {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), posture.timeoutMs);
  try {
    const res = await fetch(url, {
      ...init,
      signal: ctrl.signal,
      credentials: posture.credentials ?? 'include',
    });
    if (!res.ok) throw new Error(`http:${res.status}`);
    return (await res.json()) as T;
  } finally {
    clearTimeout(t);
  }
}

Then the route decides the posture (lane/timeout) and renders a little marker with the chosen values.

Theo Bennett
Sep 10, 2022 · 04:31 AM

Counterpoint: wrappers always drift into “why is this one request special”.

If you wrap, you need a way to inspect the final init (headers/creds/cache) and a policy for exceptions.

Avery Chen
Sep 10, 2022 · 04:36 AM

Yeah, we hit that. The only thing that made wrappers tolerable was forcing a single named posture object and rendering it in the shell.

Exceptions are allowed only via a named “override reason” string so it’s grep-able later.

Theo Bennett
Sep 10, 2022 · 04:39 AM

The override reason string is a great rule. Otherwise exceptions accumulate silently.

Hana Saito
Sep 10, 2022 · 04:44 AM

I mostly care about lifecycle: what happens on navigation and remount.

If the route intent changes, old requests must be aborted, and the UI should show that state clearly (aborted vs failed vs stale).

Keira Santos
Sep 10, 2022 · 04:52 AM

Don’t sleep on res.headers.get('content-type') checks.

We had an endpoint that started returning HTML errors and our JSON parsing blew up in confusing ways.

Amina Farouk
Sep 10, 2022 · 05:03 AM

We got rid of a class of “old request clobbered new state” bugs by tying fetch lifetime to a route key. If the key changes, abort; if the key is the same, reuse; and render the key in the UI so it’s obvious what data you’re looking at.

tsx
const doc = useRouteDoc('orders');
const key = doc.read('ordersKey');

useEffect(() => {
  const ctrl = new AbortController();
  fetch(`/api/orders?key=${key}`, { signal: ctrl.signal });
  return () => ctrl.abort();
}, [key]);

return <div data-fetch-key={key} />;
Jules Kwon
Sep 10, 2022 · 05:15 AM

I like keeping the helper pure and putting orchestration in the route boundary.

The route decides cache posture; the helper executes; the shell renders the signals.

Also worth linking: MDN AbortController.

Inez Park
Sep 10, 2022 · 05:27 AM

Timeout signals are underrated. “it hung” becomes timeout=3000ms lane=bypass and suddenly it’s actionable.

If you only ever log it, you won’t see patterns early.

Benji Rios
Sep 10, 2022 · 05:41 AM

Practical rule: standardize cache lanes as a first-class option and don’t let call sites invent stale semantics.

Most “fetch is flaky” complaints are actually “cache posture is inconsistent” complaints.