swr
swr copied to clipboard
Type error when overriding global fetcher function with null
Bug report
Description / Observed Behavior
When a global fetcher is configured using SWRConfig it can't be overridden locally by setting fetcher to null - a request still happens.
// This results in a request to "/state"
const first = useSWR("state", null);
If I set the fetcher to null in the config parameter it works, but that does not typecheck so a ts-ignore comment is needed.
// This works but TS complains:
// "Type 'null' is not assignable to type '((arg: "state") => any) | undefined'."
const second = useSWR("state2", null, {
fetcher: null,
});
A workaround is to type the config as {}:
useSWR<DataType, ErrorType, {}>("state2", null, {
fetcher: null,
});
Expected Behavior
No typescript errors displayed. In best case a null passed as fetcher should override global config.
Repro Steps / Code Example
https://codesandbox.io/p/sandbox/useswr-typing-bug-2d4prc?file=%2Fsrc%2FApp.tsx%3A10%2C32
Additional Context
SWR version 2.2.4
Tangential: why do you need to override the fetcher to null? If this is a conditional fetching, I set key to null, not a fetcher, i.e.:
const { data: customers } = useSWR(action === "list" ? "/api/customers" : null, fetcher)
@huksley I have a global SWR config that defines a fetcher. In one case I want to use swr with a null fetcher to manually control the data fetching process, e.g. call fetch on click and store the resulting value using the mutate function. Another use case for a null fetcher would be using SWR as a state manager.
I think the issue is caused by this line, where when the local fetcher is not provided (e.g., null
or undefined
), the useSWR
will fallback to use the global fetcher.
I feel that this is not a bug, because there are legitimate use cases for useSWR('key')
where the fetcher is not provided. I think your workaround is also legitimate, as it matches this type definition.
Alternatively, we could create a config option, something in line like localPause
, and then we can pause the use of the fetchers locally when this config variable is set to false
:
// `state` will not be fetched
const [isPaused, setIsPaused] = useState(false);
const state = useSWR("state", {
localPause: isPaused,
} as SWRConfiguration);