swr icon indicating copy to clipboard operation
swr copied to clipboard

Type error when overriding global fetcher function with null

Open rickythefox opened this issue 4 months ago • 3 comments

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

rickythefox avatar Feb 08 '24 09:02 rickythefox

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 avatar Feb 16 '24 08:02 huksley

@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.

rickythefox avatar Feb 16 '24 10:02 rickythefox

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);

Chopinsky avatar Apr 07 '24 22:04 Chopinsky