sajad torkamani

What are Error Boundaries?

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree. You typically use them to display a fallback UI (e.g., with a sorry message) or to log errors to a error reporting service like Sentry.

Error boundaries help you gracefully handle errors rather than show users a blank white screen. You can think of them like JavaScript’s catch blocks but for React components.

Errors that error boundaries DO NOT catch

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

Define an error boundary

Create a class component that responds to either of the lifecycle methods:

Here’s an example:

import React, { ErrorInfo } from 'react'

interface Props {
  children: React.ReactNode
}

type State = { hasError: boolean; error: Error | null }

class ErrorBoundary extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state = { hasError: false, error: null }
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.log({ error, errorInfo })
  }

  render() {
    const { hasError, error } = this.state
    console.log({ hasError, error })

    if (hasError) {
      return <>Some error occurred</> // Show whatever you need to
    }

    return this.props.children
  }
}

export default ErrorBoundary

You can then use it like this:

<ErrorBoundary>
  <MyPage />
</ErrorBoundary>

An example <ErrorScreen /> implementation might look like:

import React from 'react'
import Alert from 'react-bootstrap/Alert'
import { isDevelopment } from '../../lib/utils'
import MainLayout from '../layouts/MainLayout'
import { Container } from '../layout'

const FALLBACK_ERROR_MESSAGE = 'Something went wrong.'

type Props = { error?: Error }

const ErrorScreen: React.FC<Props> = ({
  error = new Error(FALLBACK_ERROR_MESSAGE),
}) => (
  <MainLayout>
    <Container>
      <Alert variant="danger" className="mt-4">
        {isDevelopment() ? error.stack : FALLBACK_ERROR_MESSAGE}
      </Alert>
    </Container>
  </MainLayout>
)

export default ErrorScreen

Now, whenever an error occurs inside the <MyPage> tree, end users see a generic message (e.g., Something went wrong) whilst developers can see the full error stack.

Sources

Tagged: React