Reputation: 1118
I've got a pretty basic component that does pagination. If I move pages, I'm trying to get SWR to pull from cache, but it does another api request instead.
Here is a Code.io sample. https://codesandbox.io/s/friendly-elgamal-v9sm9k?file=/src/App.js
If you look at the network tab after going to page 2, and back to page 1, it re-fetches page 1 from the api.
export const Stocks: React.FunctionComponent = () => {
interface SearchResponse {
Response: APIResponse<Array<string>>;
SearchText: string;
}
const [pageIndex, setPageIndex] = useState<number>(1);
const stocks = useRequest<Array<StockItem>>(`get-symbols?page=${pageIndex}`);
const RenderSymbols = () => {
console.log(stocks);
if (stocks?.data == undefined) return;
return stocks.data.map((f, index) => {
return (
<Stock key={index} item={f} />
);
})
}
return (
<Grid container>
<Grid item xs={12} xl={12}>
<Typography variant='h4'>Stocks</Typography>
<Grid container spacing={5}>
{RenderSymbols()}
</Grid>
<Page page={pageIndex} totalItems={stocks.totalRecords} itemsPerPage={9} pageChanged={(p) => setPageIndex(p)} />
</Grid>
</Grid>
);
};
export default Stocks;
Anytime I go to the next page in the grid, it increment pageIndex, and SWR gets called here.
export default function useRequest<T>(url: string | null): Response<T> {
const config: SWRConfiguration = {
revalidateOnFocus: false,
};
const { data, mutate, error } = useSWR<APIResponse<T>>(`${process.env.REACT_APP_URL ?? ""}${url}`,fetcher,config);
return {
data: data?.data,
isLoading: !error && !data,
isError: error,
mutate: mutate,
page: data?.page ?? 0,
totalRecords: data?.totalRecords ?? 0,
};
}
Here is my fetcher:
export default async function fetcher<JSON = any>(
input: RequestInfo,
init?: RequestInit
): Promise<JSON> {
const res = await fetch(`${input}`)
return res.json()
}
Going back and forth between pages calls a new HTTP request, rather than grabbing it from SWR cache. I'm guessing I'm doing something wrong here, just not sure what.
Upvotes: 1
Views: 8035
Reputation: 7098
SWR most certainly still uses the cached data (in SWR terms, the "stale data"). It's just that while using the stale data, it does a real request to retrieve the most updated data in the background, then updating it.
That's the main job of SWR, as stated in their home page:
SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.
To prevent fetching newer data and use only stale data, turn the revalidateIfStale
option off.
useSWR(url, fetcher, {
...config,
revalidateIfStale: false // default is `true`
});
Depending on your use cases, you probably want these options off too:
revalidateOnMount
revalidateOnFocus
revalidateOnReconnect
As the other answer said, you can also use useSWRImmutable
, which turns all the above options off automatically for you.
Upvotes: 4