# Error Boundaries

Error boundaries are React components that can catch and handle errors that occur in any of their children components, most commonly by defining some kind of fallback UI that renders and informs the user of the error.

Currently, there is not any hook equivalent that can create the behavior required. Hook-based error boundaries are on the roadmap but, for now, we are stuck with class components

# Usage

If any component within the opening and closing tags of an error boundary component throw an error, everything within the tags will be replaced by the fallback UI. For example:


<ErrorBoundary fallback={<ErrorReportingComponent />}>
  <TextArea>Some Text</TextArea>
  <ReactComponentA propA="foo" propB="bar"/>
  <ReactComponentWithChildren>
    <ChildComponent icon="👶"/>
  </ReactComponentWithChildren>
</ErrorBoundary>

In this example, the fallback component <ErrorReportingComponent> will render in place of the <TextArea>, <ReactComponentA>, <ReactComponentWithChildren> and its <ChildComponent>. When deciding where and how to place an error boundary, it helps to think visually.

If you have a single page with an index table, and the index table doesn't load, the entire page could be rendered non-functional. It makes sense to wrap the entire page.

If you have a dashboard with 8 widgets, it makes more sense to wrap them independently. If one widget fails, the fallback component can inform the user while the rest of the page functions normally.

# Route Errors

react-router-dom will not throw errors to components outside of its own library, so errors in those components cannot be caught by our standard error boundaries. To catch these types of errors, we create a component that uses react-router-dom's useRouteError hook and assign it as the errorComponent prop on our Route components.

Examples
// ❌ Bad: Leaving error handling of Routes to standard Error Boundaries
// Any errors that occur in these Routes will not be caught by the GlobalErrorBoundary
// and the application will crash out to the React standard error screen.
<GlobalErrorBoundary fallback={<UnknownErrorEmptyState headingAs="h2" />}>
  <Route 
    element={<VinylRoutingProvider />} 
  >
      <Route path="/" element={<Layout />}>
          <Route />
          ...
          <Route />
      </Route>
  </Route>
</GlobalErrorBoundary>

// ✅ Good: Creating a boundary with the useRouter hook and passing it to a 
// Route's `errorElement` prop

export const GlobalRouteErrorBoundary = () => {
	const error = useRouteError();

  return <p>{error.message}</p>
}

------------------------------------------------------

<Route 
  element={<VinylRoutingProvider />} 
  errorElement={<GlobalRouteErrorBoundary />}
>
	// Errors in any of these child routes will be passed up the tree until they 
    // reach the Route with an errorElement
    <Route path="/" element={<Layout />}>
		    <Route />
        ...
        <Route />
    </Route>
</Route>      

# Recommended Reading

Brandon Dail's "Fault Tolerance" is a quick read and a great write up on responsible error boundary usage and best practices with visual examples.