--- id: error-boundaries title: Error Boundaries permalink: docs/error-boundaries.html --- In the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to [emit](https://github.com/facebook/react/issues/4026) [cryptic](https://github.com/facebook/react/issues/6895) [errors](https://github.com/facebook/react/issues/8579) on next renders. These errors were always caused by an earlier error in the application code, but React did not provide a way to handle them gracefully in components, and could not recover from them. ## Introducing Error Boundaries A JavaScript error in a part of the UI shouldn’t break the whole app. To solve this problem for React users, React 16 introduces 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. > Note > > Error boundaries do **not** catch errors for: > > * Event handlers ([learn more](#how-about-event-handlers)) > * Asynchronous code (e.g. `setTimeout` or `requestAnimationFrame` callbacks) > * Server side rendering > * Errors thrown in the error boundary itself (rather than its children) A class component becomes an error boundary if it defines a new lifecycle method called `componentDidCatch(error, info)`: ```js{7-12,15-18} 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
You can also see the filenames and line numbers in the component stack trace. This works by default in [Create React App](https://github.com/facebookincubator/create-react-app) projects:
If you don’t use Create React App, you can add [this plugin](https://www.npmjs.com/package/babel-plugin-transform-react-jsx-source) manually to your Babel configuration. Note that it’s intended only for development and **must be disabled in production**.
> Note
>
> Component names displayed in the stack traces depend on the [`Function.name`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) property. If you support older browsers and devices which may not yet provide this natively (e.g. IE 11), consider including a global polyfill in your bundled application, such as [core-js](https://github.com/zloirock/core-js) or [babel-polyfill](https://babeljs.io/docs/usage/polyfill/). Alternatively, you may explicitly set the [`displayName`](/docs/react-component.html#displayname) property on all your components.
## How About try/catch?
`try` / `catch` is great but it only works for imperative code:
```js
try {
showButton();
} catch (error) {
// ...
}
```
However, React components are declarative and specify *what* should be rendered:
```js
```
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 `setState` somewhere deep in the tree, it will still correctly propagate to the closest error boundary.
## How About Event Handlers?
Error boundaries **do not** catch errors inside event handlers.
React doesn't need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle hooks, the event handlers don't happen during rendering. So if they throw, React still knows what to display on the screen.
If you need to catch an error inside event handler, use the regular JavaScript `try` / `catch` statement:
```js{8-12,16-19}
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
}
handleClick = () => {
try {
// Do something that could throw
} catch (error) {
this.setState({ error });
}
}
render() {
if (this.state.error) {
return