vercel / swr

React Hooks for Data Fetching
https://swr.vercel.app
MIT License
30.62k stars 1.22k forks source link

SWR do not revalidate cache, but keys have changed. #2210

Closed dolie closed 2 years ago

dolie commented 2 years ago

Bug report

Cache is not revalidated, but keys have changed.

Description / Observed Behavior

SWR in Preact app (using signals) cache is not revalidated when keys have changed. After clearing cache, it does not refetch when keys change, and use cache instead.

Capture d’écran 2022-10-23 à 20 52 11

As you can see, cache keys are differents. But the values are the same. (API returns something different for each locals, also local ja-JP should return error. I tried keys with both object and string).

Capture d’écran 2022-10-23 à 20 45 57

Expected Behavior

SWR detect correctly that keys have changed and do not use cache.

Repro Steps / Code Example

// use-countries.ts
import useSWR from "swr";
import { selectedLocale } from "@/store/global";

interface Country {
  id: string;
  label: string;
}

export default function useCountries(){

  const options = {
    headers: {
      'accept-language': selectedLocale.value
    }
  }

  const { data, error, mutate } = useSWR<Country[], any>(
    ["/v0/countries", options]
  );

  const loading = !data && !error;

  return {
    loading,
    countries: data,
    error,
    mutate,
  };
}
// fetcher.ts
export const fetcher = (
  url: string,
  options: FetcherOptions = {}
) => {

  const queryUrl = host + url + '?' + new URLSearchParams({
    api_key,
    ...options.params
  })

  return fetch(queryUrl, 
    {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        ...options.headers // dynamic 'accept-language' here
      },
    })
    .then(res => res.json())
}

Additional Context

"@preact/signals": "^1.1.1", "preact": "^10.11.0", "preact-router": "^4.1.0", "swr": "^1.3.0"

dolie commented 2 years ago

I can see that SWR import 'react' under the hood... Is there any config to use preact/hooks instead ? Maybe it is the reason why it does not work.

dolie commented 2 years ago

I solved my problem. 1) SWR run as expected with Preact (FYI it adds nothing to the bundle, even with React as a dependency). 2) It seems that the browser treat the calls with different headers as the same calls. So it return the same cache for en-US, fr-FR, ja-JP. (it does a Map only with url as keys) 3) In conclusion : I must add locale as a querystring so it forces the browser to do not see as the same API call, and make a new fetch (even if the API don't care about the querystring but only about the headers) and do not return cache.

Thank you for this great lib !