swr
swr copied to clipboard
error thrown in mutate bubbles up to error of useSWR hook
Bug report
Description / Observed Behavior
What kind of issues did you encounter with SWR?
When calling mutate with a function as 2nd argument and an error is thrown inside that function, the error will bubble up to error
returned by useSWR.
Expected Behavior
How did you expect SWR to behave here?
The error should not bubble up, as it mixes up data fetching with data mutation errors.
As written in the API Options
error: error thrown by fetcher (or undefined)
Correct would be error thrown by fetcher or inside mutate (or undefined)
I don't know if this is an intentional design decision or just a bug.
Repro Steps / Code Example
Or share your code snippet or a CodeSandbox link is also appreciated!
I created two sandboxes:
To workaround the problem, I created this function which makes sure no error is bubbling up:
import { mutate } from "swr";
function safeMutate(key, action, revalidate) {
return new Promise((resolve, reject) => {
mutate(
key,
(oldValue) => {
return action(oldValue).catch((error) => {
reject(error);
!revalidate && mutate(key, null); // wont work without null
});
},
revalidate
).then(resolve);
});
}
One drawback is that when setting revalidate
to false
and an error is thrown, we need to mutate to null to force revalidation (see comment "wont work without null").
As described in the docs
many POST APIs will just return the updated data directly, so we don’t need to revalidate again.
In fact, we need to revalidate at least when there is an error to make it go away.
Additional Context
SWR version 1.0.1
Thank you for opening this! This is currently by design, but I think we can improve it so we can differentiate "fetch" errors and "mutate" errors (haven't found a good design for it yet). For the same reason, we need the data
and isValidating
states to be context-aware (related to #1316). One way to simplify all these is using the upcoming useSWRMutation
feature (#1450).
I'll mark this issue as "discussion".
I just discovered the SWR 1.1.0 also swallows null errors. https://codesandbox.io/s/cocky-smoke-kv4ir?file=/src/App.tsx
In this scenario, opts
is undefined, so SWR encounters an error on !opts.skip
. Enabling the ts null check flag would've likely caught it, but it's not enabled in this codebase.
When SWR encounters this error, it stays silent. the returned error
stays undefined.
const { data } = useSWR(
() => (somethingValid && !opts.skip ? key : null),
(key) => fetcher(api, key)
);
Is this expected behavior?
@dangdennis That might not be related to this thread, but did you mean conditional fetching (the key function throws an error, which pauses the request).
Hah, actually you’re very right. I forgot that a thrown exception are treated the same as nulls.