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