img
AboutContactBlogGet in touch

6 min read

What Are React Error Boundaries and How Can You Implement Them?

Interested in generating passive income? Join our partnership program and receive a commission on each new client referral. Learn more.

react error boundary

Have you ever been in a situation in development where everything is set up and works properly, but the application crashes production because of a missed little error? Then the client calls you and tells you the whole screen goes white while clicking some button. The react error boundary has blessed us with precisely those scenarios. 

What problem do you see in the following code?

const navList = [
    {
        slug: 'home',
        id: 1,
        name: 'Home'
    },
    {
        slug: 'profile',
        id: 2,
        name: 'My Profile'
    }
]
 
const Navigation = () => {
     if (''.length < 0) {
        // ?️ calling React hook conditionally
        useEffect(() => {
            console.log('hello world')
        })
    }
 
    return (
        <ul>
            {navList.map(nav => <li key={nav.id}>{nav.name}</li>)}
        </ul>
    )
}

If you run this code, it will crash because of breaking the rule of working on hooks. And the error in development might be in a console (Rendered more hooks than during the previous render). Or you might not get an error at all; it depends on the project's configuration. These types of problems create a white screen on a production. To solve this problem smoothly, we can create an Error Boundary component that can solve all of the abovementioned issues. If you want to create such a component, it is necessary to consider the following:

  • It should be a Class component.
  • Must implement "getDerivedStatFromError" or "componentDidCatch"

Fortunately, the react-error-boundary package provides us with all the instruments necessary to fix the errors, so we no longer have to spend extra time writing it. So let's add it to the project:

npm install react-error-boundary
yarn add react-error-boundary  

The easiest way to use this component is to wrap the whole project in it. We can also use it in any file and create components with different visuals and functionalities for different pages.

import { createRoot } from 'react-dom/client'
 
import { ErrorBoundary } from 'react-error-boundary'
 
const container = document.getElementById('root')
const root = createRoot(container)
 
function RuntimeErrorFallback(props) {
  const { resetErrorBoundary, error } = props
 
  return (
    <div>
      <p>Found error:</p>
      <pre style={{ color: 'red' }}>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
      <button
 		  onClick={() => {
                        window.navigation.navigate('/')
                        resetErrorBoundary()
                    }}
                >
                    Main Page
                </button >
 
    </div>
  )
}
 
const App = () => (
      <>
        <ErrorBoundary FallbackComponent={RuntimeErrorFallback}>
            <Navigation />
        </ErrorBoundary>
      </>
    )
  
root.render(<App />)

This is the case when we place the whole application under one component. We can also put any component in its boundary, preventing us from crashing the entire application and ensuring replacing only the components with errors.

Let's go through a more complex example:

const InputFallback = ({ error, resetErrorBoundary }) => {
    return (
        <div>
            <p>Something went wrong:</p>
            <pre style={{ color: 'red' }}>{error.message}</pre>
            <button onClick={resetErrorBoundary}>Type another word</button>
        </div>
    )
}
 
const HandleInput = ({ username }) => {
  if (username === "redberry") {
    throw new Error("? Don’t Type Redberry to avoid error. ?");
  }
  return `Hi ${username}`;
}
 
const App = () => {
  const [username, setUsername] = useState("");
  const usernameRef = useRef(null);
 
  return (
    <div>
      <label htmlFor="username">{`Username (don't type "Redberry"): `}</label>
      <input
        placeholder={`type "redberry"`}
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        ref={usernameRef}
        id="username"
      />
      <div>
        <ErrorBoundary
          FallbackComponent={InputFallback}
          onReset={() => {
            setUsername("");
            usernameRef.current.focus();
          }}
          resetKeys={[username]}
        >
          <HandleInput username={username} />
        </ErrorBoundary>
      </div>
    </div>
  );
};

If you type "redberry," the HandleInput component will be replaced with a component indicated in FallbackComponent. Since HandleInput shows an error in case the information in the input equals "redberry." To fix it, you should change the username. Unfortunately, some errors are impossible to catch:

Error boundaries do not catch errors for:

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

For further information, visit the Github page

Conclusion

React Error Boundaries are a crucial tool for handling unexpected errors that occur within a React component and preventing them from propagating to the parent components, potentially causing a complete UI breakdown. With the help of Error Boundaries, developers can implement customized error-handling strategies and display a fallback UI to the user, preserving the user experience.

It is important to note that Error Boundaries only catch errors within the render() method or in the component's lifecycle methods. They will not catch errors in asynchronous code such as setTimeout() or network requests. Additionally, having at least one global Error Boundary component in your application is recommended to handle errors that may occur outside of a specific component. Finally, Error Boundaries should only be used for debugging and fallback UI purposes and not as a means of catching and fixing errors in production.

 

Written by: Nikoloz Palagashvili

Table of Contents

img

Meet the authors

We are a 200+ people agency and provide product design, software development, and creative growth marketing services to companies ranging from fresh startups to established enterprises. Our work has earned us 100+ international awards, partnerships with Laravel, Vue, Meta, and Google, and the title of Georgia’s agency of the year in 2019 and 2021.

img
Contact us