javascript 52 lines · 10 steps

Building a stale-while-revalidate hook in React

A useSWR hook serves cached data instantly while refetching in the background, deduping concurrent requests.

Explained by highlit
1import { useState, useEffect, useCallback, useRef } from 'react';
2 
3const cache = new Map();
4const inflight = new Map();
5 
6function fetchAndStore(key, fetcher) {
7 if (inflight.has(key)) return inflight.get(key);
8 const promise = Promise.resolve(fetcher(key))
9 .then((data) => {
10 cache.set(key, { data, timestamp: Date.now() });
11 inflight.delete(key);
12 return data;
13 })
14 .catch((err) => {
15 inflight.delete(key);
16 throw err;
17 });
18 inflight.set(key, promise);
19 return promise;
20}
21 
22export function useSWR(key, fetcher) {
23 const entry = key ? cache.get(key) : undefined;
24 const [data, setData] = useState(entry?.data);
25 const [error, setError] = useState(undefined);
26 const [isValidating, setIsValidating] = useState(false);
27 const fetcherRef = useRef(fetcher);
28 fetcherRef.current = fetcher;
29 
30 const revalidate = useCallback(async () => {
31 if (!key) return;
32 setIsValidating(true);
33 try {
34 const fresh = await fetchAndStore(key, fetcherRef.current);
35 setData(fresh);
36 setError(undefined);
37 } catch (err) {
38 setError(err);
39 } finally {
40 setIsValidating(false);
41 }
42 }, [key]);
43 
44 useEffect(() => {
45 if (!key) return;
46 const cached = cache.get(key);
47 if (cached) setData(cached.data);
48 revalidate();
49 }, [key, revalidate]);
50 
51 return { data, error, isValidating, mutate: revalidate };
52}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Module-level Maps give a cache and dedup registry that survive component remounts and are shared across every hook instance.
  2. 2Tracking in-flight promises by key collapses concurrent requests for the same data into a single network call.
  3. 3Serving cached data first and revalidating after keeps the UI instant while still converging on fresh values.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a stale-while-revalidate hook in React — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code