I have an error boundary with a retry button that updates its own key to rerender the whole subtree.
I want to retry the failed request on rerender (I use shouldRetryOnError: false).
I tried to rethrow the error around useSWR. I get the logs, but on next render, the xhr request isn't refired, but SWR reraises the same error as before :(
try {
console.log("requesting", { key });
result = useSWR(key, fetcher, { suspense: true });
} catch (err) {
console.log("error", { key });
trigger(key);
throw err;
}
const { data, isValidating, revalidate } = result;
Any pointer?
Thx a lot!
It seems like trigger doesn't work because here we don't get any updaters.
The reason we don't have any updaters is because they're set up in useLayoutEffect hook and in suspense mode we don't get to render and setup them if first request errors out
I think this particular issue could possibly be fixed if we set up errorKey's cache entry expiration before re-throwing it
Hi, since #231 got merged you can now clear up the cached error value on your own.
For your example it might look something like this:
import { cache } from 'swr';
// ...
try {
console.log("requesting", { key });
result = useSWR(key, fetcher, { suspense: true });
} catch (err) {
console.log("error", { key });
const [, , errorKey] = cache.serializeKey(key);
cache.delete(errorKey, false);
throw err;
}
// ...
const { data, isValidating, revalidate } = result;
Thanks a lot @nulladdict, you really helped me.
This works for me:
let result;
try {
result = useSWR(key, fetcher, { suspense: true });
} catch (err) {
const [, , errorKey] = cache.serializeKey(key);
window.setTimeout(() => cache.delete(errorKey, false));
throw err;
}
const { data, isValidating, revalidate } = result;
As you can see I have to delete the cache entry after rethrowing, otherwise it loops indefinitely.
The error promise is never received by my error boundary, useSWR justs goes nuts and short cuts the whole rerendering. Same with cache.__cache.delete.
Do you have any idea why deleting the entry from the cache could be somehow affecting Suspense's logic?
Hi @bbenezech, I think the better approach is to clear out cached error in designated error boundary component
Here's a codesandbox example of approach I've been using
Couple points to mention:
ErrorGuard component we clear cached entry when user clicks the button, but we could also just clear it in setState callback inside componentDidCatch method insteadAwesome! I love this, much better. Works for me.
I was confused with the suspenders in the logs, thank you for the detailed explanation.
I think we should close this?
Most helpful comment
Hi @bbenezech, I think the better approach is to clear out cached error in designated error boundary component
Here's a codesandbox example of approach I've been using
Couple points to mention:
ErrorGuardcomponent we clear cached entry when user clicks the button, but we could also just clear it insetStatecallback insidecomponentDidCatchmethod instead