Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using React error boundary with react router

We are trying to use react-error-boundary with react-router (v6) but seems like we need to wrap every route element with an error boundary as shown below

import { ErrorBoundary } from "react-error-boundary";

export const AppRoutes = createBrowserRouter([
{
   path: "/",
   element: <ErrorBoundary FallbackComponent={GlobalError}><Login /></ErrorBoundary>
},
{
  path: "login",
  element: <ErrorBoundary FallbackComponent={GlobalError}><Login /></ErrorBoundary>,
},
{
  path: "trans",
  element: <ErrorBoundary FallbackComponent={GlobalError}><Trans /></ErrorBoundary>
),
{
  path: "*",
  element: <ErrorBoundary FallbackComponent={GlobalError}><RouteNotFound /></ErrorBoundary>
}]);

Do we have a simpler way to do this like below? Any configuration flag in react-router to bubble up the error

import { ErrorBoundary } from "react-error-boundary";

<ErrorBoundary FallbackComponent={GlobalError}>
  <Header />
    <RouterProvider router={AppRoutes} />
  <Footer />
</ErrorBoundary>

Below is the screenshot of the error we get when we wrap the RouterProvider inside the Error Boundary

enter image description here

Below is a sample code for the Trans component to throw an error.

export function Trans() {
  const [error, setError] = useState(null);

  if (error) {
    throw error;
  }

  useEffect(() => {
    setTimeout(() => setError("This is error"), 2000);
   }, []);

  return <p>This is Trans</p>;
} 
like image 467
user3205479 Avatar asked Apr 22 '26 04:04

user3205479


1 Answers

The code snippets should work, but if you are wanting to make the code more DRY then instead of wrapping each route individually you can create a layout route that renders an Outlet component wrapped by the ErrorBoundary component.

Example:

import { createBrowserRouter, Outlet } from 'react-router-dom';
import { ErrorBoundary } from "react-error-boundary";

const ErrorBoundaryLayout = () => (
  <ErrorBoundary FallbackComponent={GlobalError}>
    <Outlet />
  </ErrorBoundary>
);

export const AppRoutes = createBrowserRouter([
  {
    element: <ErrorBoundaryLayout />,
    children: [
      {
        path: "/",
        element: <Login />,
      },
      {
        path: "login",
        element: <Login />,
      },
      {
        path: "trans",
        element: <Trans />,
      },
      {
        path: "*",
        element: <RouteNotFound />,
      },
    ],
  },
]);

You should note this for React Error Boundaries:

Note

Error boundaries do not catch errors for:

  • Event handlers (learn more)
  • Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
  • Server side rendering
  • Errors thrown in the error boundary itself (rather than its children)

In your Trans component example you are using a setTimeout to set some error state. I can only guess that maybe the thought process here is that some errors are considered "unrecoverable" so the error boundary kicks in and handles it, otherwise errors occurring in the points above are considered "recoverable" and your component code should be coded to potentially handle the scenarios of asynchronous issues like failed fetch requests, etc.

like image 84
Drew Reese Avatar answered Apr 24 '26 20:04

Drew Reese