62Implement useQuery() with caching, retries, and stale data
mediumAbout 45 minutesCodingreacthookscachinguseSyncExternalStore
Problem
Implement a small version of React Query: useQuery(key, fetcher, { staleTime = 0, retry = 2, retryDelay = 10 }). It returns { data, error, status, isFetching, refetch }, where status is "loading", "success" or "error".
The cache is shared by every component, keyed by the string key:
- If the cache has data, return it immediately. If that data is older than
staleTimems, also refetch in the background (stale-while-revalidate) and setisFetchingtotrue. - Several components asking for the same key at the same time cause one request.
- A failing fetcher is retried up to
retrytimes, waitingretryDelay * 2 ** attemptms between attempts. After the last failure,statusis"error", unless older data exists, which stays visible. - When a fetch completes, every component using that key re-renders with the new data.
function UserBadge({ id }) {
const { data, status } = useQuery(`user:${id}`, () => api.getUser(id), { staleTime: 30_000 });
if (status === "loading") return <Skeleton />;
if (status === "error") return <span>Unavailable</span>;
return <span>{data.name}</span>;
}Try it yourself
Write your solution, run it, then submit to check it against the tests.
App.jsxReact + DOM
Step-by-step
A module-level Map from key to an entry: { data, error, updatedAt, promise, isFetching, version, listeners }. Living outside React is what lets every component share it.
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 5 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.