ErrorBoundary (v2)

You can opt-in to the new ErrorBoundary API with a future flag in Remix config.

  1. /** @type {import('@remix-run/dev').AppConfig} */
  2. module.exports = {
  3. future: {
  4. v2_errorBoundary: true,
  5. },
  6. };

A Remix ErrorBoundary component works just like normal React error boundaries, but with a few extra capabilities. When there is an error in your route component, the ErrorBoundary will be rendered in its place, nested inside any parent routes. ErrorBoundary components also render when there is an error in the loader or action functions for a route, so all errors for that route may be handled in one spot.

The most common use-cases tend to be:

  • You may intentionally throw a 4xx Response to trigger an error UI
    • Throwing a 400 on bad user input
    • Throwing a 401 for unauthorized access
    • Throwing a 404 when you can’t find requested data
  • React may unintentionally throw an Error if it encounters a runtime error during rendering

To obtain the thrown object, you can use the useRouteError hook. When a Response is thrown, it will be automatically unwrapped into an ErrorResponse instance with state/statusText/data fields so that you don’t need to bother with await response.json() in your component. To differentiate thrown Response‘s from thrown Error‘s’ you can use the isRouteErrorResponse utility.

  1. import {
  2. isRouteErrorResponse,
  3. useRouteError,
  4. } from "@remix-run/react";
  5. export function ErrorBoundary() {
  6. const error = useRouteError();
  7. if (isRouteErrorResponse(error)) {
  8. return (
  9. <div>
  10. <h1>
  11. {error.status} {error.statusText}
  12. </h1>
  13. <p>{error.data}</p>
  14. </div>
  15. );
  16. } else if (error instanceof Error) {
  17. return (
  18. <div>
  19. <h1>Error</h1>
  20. <p>{error.message}</p>
  21. <p>The stack trace is:</p>
  22. <pre>{error.stack}</pre>
  23. </div>
  24. );
  25. } else {
  26. return <h1>Unknown Error</h1>;
  27. }
  28. }