I am currently using React-Query and Error Boundaries to manage server side states and errors.
Current behavior
- Query Fails throw error. (500 Server Error)
- ApiErrorFallback catches error, but it cannot handle, so pass it to GlobalErrorFallback.
- GlobalErrorFallback shows error message and button to reset query and error boundary.
- When button is clicked, it does not show loading skeleton that I had in Suspense fallback.
Expected behavior
- When button is clicked, the query with key of ['errorQuery'] should reset and show loading skeleton, and show the result.
I tried having 400 error so that ApiErrorFallback can handle which worked. But I am not sure why it is not resetting the query when it is passed to GlobalErrorFallback.
const App = () => {
const { reset } = useQueryErrorResetBoundary();
const location = useLocation();
// Global Error Boundary
return (
<ErrorBoundary
key={location.pathname}
onReset={reset}
fallbackRender={GlobalErrorFallback}
>
<Suspense fallback={<SuspenseFallback />}>
<Router />
</Suspense>
</ErrorBoundary>
);
};
const Router = () => {
return (
<Routes>
<Route element={<PrivateRoute />}>
<Route path="/" element={<MainPage />} />
</Route>
</Routes>
);
};
// Expected Error Boundary
const MainPage = () => {
const { reset } = useQueryErrorResetBoundary();
const location = useLocation();
return (
<ErrorBoundary
key={location.pathname}
onReset={reset}
fallbackRender={ApiErrorFallback}
>
<Suspense fallback={<Skeleton />}>
<ComponentThatWillThrowError />
</Suspense>
</ErrorBoundary>
);
};
const ComponentThatWillThrowError = () => {
const { data } = useQuery(["errorQuery"], errorRequest, { suspense: true });
return <div>{data}</div>;
};
const ApiErrorFallback = ({ error, resetErrorBoundary }) => {
const { status } = error?.response;
switch (status) {
case 400:
case 401: {
// ... handle errors here
return <button onClick={() => resetErrorBoundary}>Try Again</button>;
}
default: {
throw error; // pass error to global error boundary
}
}
};
const GlobalErrorFallback = ({ error, resetErrorBoundary }) => {
// This does not reset the query
return (
<>
<h1>Something went wrong</h1>
<button onClick={() => resetErrorBoundary}>Try Again</button>
</>
);
};