0

I am currently using React-Query and Error Boundaries to manage server side states and errors.

Current behavior

  1. Query Fails throw error. (500 Server Error)
  2. ApiErrorFallback catches error, but it cannot handle, so pass it to GlobalErrorFallback.
  3. GlobalErrorFallback shows error message and button to reset query and error boundary.
  4. 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>
    </>
  );
};
1
  • can you show this in a codesandbox? Commented Apr 7, 2023 at 19:24

1 Answer 1

0

Most likely you are using the ErrorBoundary component from the react-error-boundary library. In fallbackRender you need to pass the component, which in turn accepts an object with resetErrorBoundary function. The error in your code is that in the button onClick handler you return the resetErrorBoundary function but do not execute it.

Fix this code to this

return <button onClick={() => resetErrorBoundary()}>Try Again</button>;

and everything will work

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.