HomeFrameworksReactJSIntroducing Error Boundaries in React 16

Introducing Error Boundaries in React 16

As React 16 release is getting closer, there are few changes to how React handles JavaScript errors inside components. These changes are included in React 16 beta versions, and will be a part of React 16.

By the way,Ā the first beta of React 16 is for you to try!

#Introduction Error Boundaries

The whole app shouldn’t break as a result of one stupid error in a part of the UI. To solve this problem, React 16 introduced a new concept of an “error boundary”.

Error boundaries are React components thatĀ catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UIĀ instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

A class component becomes an error boundary if it defines a new lifecycle method calledĀ componentDidCatch(error, info):


class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

Then you can use it as a regular component:


<ErrorBoundary>

  <MyWidget />

</ErrorBoundary>

TheĀ componentDidCatch()Ā method works like a JavaScriptĀ catch {}Ā block, but for components. Only class components can be error boundaries. In practice, most of the time youā€™ll want to declare an error boundary component once and use it throughout your application.

Note thatĀ error boundaries only catch errors in the components below them in the tree. An error boundary canā€™t catch an error within itself. If an error boundary fails trying to render the error message, the error will propagate to the closest error boundary above it. This, too, is similar to howĀ catch {}Ā block works in JavaScript.

#Where to Place Error Boundaries

The granularity of error boundaries is up to you. You can use it the top-level route components to display a ā€œOops…Something went wrongā€ message to the user or you may wrap individual widgets in an error boundary to protect them from crashing the rest of the application.

#New Behavior for Uncaught Errors

This change has an important implication.Ā As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree.

This change also implies that as you plan to migrate to React 16, you will likely uncover existing crashes in your application that have been unnoticed before. Adding error boundaries lets you provide better user experience when something goes wrong.

Lets take an example of the Facebook Messenger, this famous messenger app of Facebook wraps the contents of the sidebar, the info panel, the conversation log, and the message input into their own separate error boundaries. If at any point of time some component in these UI area crashes, the rest of them remain interactive.

#Component Stack Traces

React 16 prints all errors that occurred during rendering to the console in development, even if the application accidentally swallows them. In addition to the error message and the JavaScript stack, it also provides component stack traces. Now you can see where exactly in the component tree the failure has happened:

Component stack traces in error message - react error boundaries
Courtesy: ReactJS Facebook

You can also see the filenames and line numbers in the component stack trace. This works by default inĀ Create React AppĀ projects:

Component stack traces with line numbers in error message - react error boundaries

If you donā€™t use Create React App, you can addĀ this pluginĀ manually to your Babel configuration. Note that itā€™s intended only for development andĀ must be disabled in production.

#Why Not Use try / catch ?

tryĀ /Ā catchĀ is great but it only works for imperative code:

try {
  showButton();
} catch (error) {
  // ...
}

However, React components are declarative and specifyĀ whatĀ should be rendered:

<Button />

Error boundaries preserve the declarative nature of React, and behave as you would expect. For example, even if an error occurs in aĀ componentDidUpdateĀ hook caused by aĀ setStatesomewhere deep in the tree, it will still correctly propagate to the closest error boundary.

Source Viva:Ā https://facebook.github.io/react/blog/2017/07/26/error-handling-in-react-16.html

RELATED ARTICLES

Most Popular