Home > Software design >  SWR not pulling from cache
SWR not pulling from cache

Time:08-11

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.

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,
  };
} 

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.

CodePudding user response:

If you don't want to revalidate the data at all it's better to use useSWRImmutable (more).

If you just want to increase cache TTL then you need to look into dedupingInterval option which is by default only equals to 2000ms

CodePudding user response:

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.

  • Related