Why are my queued retries still applying stale data in React?

Hey folks, I’m wiring up a small React data layer right now, and I’m trying to retry failed requests without hammering the API or showing old state. The annoying part is a slower retry can land after a newer fetch and still win, so the UI snaps back to stale data.

let version = 0;

async function loadUser(id: string) {
  const current = ++version;
  const data = await fetchUserWithRetry(id);

  if (current === version) {
    setUser(data);
  }
}

Is there a better pattern for retry plus caching so older responses do not overwrite newer state when requests finish out of order?

WaffleFries

@WaffleFries yup, the bug is the single version counter. That gives you global last-write-wins, so a request for user 42 can get invalidated by a newer request for user 7, which is not really what you want.

I would track freshness per id, and if you can, cancel the old request too so you are not retrying work nobody cares about anymore.


js
const inflight = new Map();

async function loadUser(id) {
  inflight.get(id)?.abort();

  const controller = new AbortController();
  const token = Symbol(id);

  inflight.set(id, { token, controller });

  try {
    const data = await fetchUserWithRetry(id, { signal: controller.signal });

    if (inflight.get(id)?.token === token) {
      setUser(data);
    }
  } catch (err) {
    if (err.name !== "AbortError") throw err;
  }
}

Same idea for cache: key it by id, and only write the result if that request is still the current one for that same id. That stops a slow retry from snapping the UI back to old data.

Sarah