Error Handling in React 16

July 26, 2017 by Dan Abramov

As React 16 release is getting closer, we would like to announce a 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, we just released the first beta of React 16 for you to try!

Behavior in React 15 and Earlier

In the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to emit cryptic errors 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.

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) {
    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:

  <MyWidget />

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.

Live Demo

Check out this example of declaring and using an error boundary with React 16 beta.

Where to Place Error Boundaries

The granularity of error boundaries is up to you. You may wrap top-level route components to display a “Something went wrong” message to the user, just like server-side frameworks often handle crashes. You may also 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.

We debated this decision, but in our experience it is worse to leave corrupted UI in place than to completely remove it. For example, in a product like Messenger leaving the broken UI visible could lead to somebody sending a message to the wrong person. Similarly, it is worse for a payments app to display a wrong amount than to render nothing.

This change means that as you 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.

For example, Facebook Messenger wraps content of the sidebar, the info panel, the conversation log, and the message input into separate error boundaries. If some component in one of these UI areas crashes, the rest of them remain interactive.

We also encourage you to use JS error reporting services (or build your own) so that you can learn about unhandled exceptions as they happen in production, and fix them.

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

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

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 {
} 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 setState somewhere deep in the tree, it will still correctly propagate to the closest error boundary.

Naming Changes from React 15

React 15 included a very limited support for error boundaries under a different method name: unstable_handleError. This method no longer works, and you will need to change it to componentDidCatch in your code starting from the first 16 beta release.

For this change, we’ve provided a codemod to automatically migrate your code.

React v15.6.0

June 13, 2017 by Flarnie Marchan

Today we are releasing React 15.6.0. As we prepare for React 16.0, we have been fixing and cleaning up many things. This release continues to pave the way.

Improving Inputs

In React 15.6.0 the onChange event for inputs is a little bit more reliable and handles more edge cases, including the following:

  • not firing when radio button is clicked but not changed (issue 1471)
  • changing an input of type range with the arrow keys (issue 554)
  • pasting text into a text area in IE11 (issue 7211)
  • auto-fill in IE11 (issue 6614)
  • clearing input with 'x' button or right-click 'delete' in IE11 (issue 6822)
  • not firing when characters are present in the input on render in IE11 (issue 2185)

Thanks to Jason Quense and everyone who helped out on those issues and PRs.

Less Noisy Deprecation Warnings

We are also including a couple of new warnings for upcoming deprecations. These should not affect most users, and for more details see the changelog below.

After the last release, we got valuable community feedback that deprecation warnings were causing noise and failing tests. In React 15.6, we have downgraded deprecation warnings to use console.warn instead of console.error. Our other warnings will still use console.error because they surface urgent issues which could lead to bugs. Unlike our other warnings, deprecation warnings can be fixed over time and won't cause problems in your app if shipped. We believe that downgrading the urgency of deprecation warnings will make your next update easier. Thanks to everyone who was involved in the discussion of this change.


We recommend using Yarn or npm for managing front-end dependencies. If you're new to package managers, the Yarn documentation is a good place to get started.

To install React with Yarn, run:

yarn add react@^15.6.0 react-dom@^15.6.0

To install React with npm, run:

npm install --save react@^15.6.0 react-dom@^15.6.0

We recommend using a bundler like webpack or Browserify so you can write modular code and bundle it together into small packages to optimize load time.

Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, make sure to use the production build.

In case you don't use a bundler, we also provide pre-built bundles in the npm packages which you can include as script tags on your page:

We've also published version 15.6.0 of react and react-dom on npm, and the react package on bower.


15.6.0 (June 13, 2017)


  • Downgrade deprecation warnings to use console.warn instead of console.error. (@flarnie in #9753)
  • Add a deprecation warning for React.createClass. Points users to create-react-class instead. (@flarnie in #9771)
  • Add deprecation warnings and separate module for React.DOM factory helpers. (@nhunzaker in #8356)
  • Warn for deprecation of React.createMixin helper, which was never used. (@aweary in #8853)

React DOM

  • Add support for CSS variables in style attribute. (@aweary in #9302)
  • Add support for CSS Grid style properties. (@ericsakmar in #9185)
  • Fix bug where inputs mutated value on type conversion. (@nhunzaker in #9806)
  • Fix issues with onChange not firing properly for some inputs. (@jquense in #8575)
  • Fix bug where controlled number input mistakenly allowed period. (@nhunzaker in #9584)
  • Fix bug where performance entries were being cleared. (@chrisui in #9451)

React Addons

  • Fix AMD support for addons depending on react. (@flarnie in #9919)
  • Fix isMounted() to return true in componentWillUnmount. (@mridgway in #9638)
  • Fix react-addons-update to not depend on native Object.assign. (@gaearon in #9937)
  • Remove broken Google Closure Compiler annotation from create-react-class. (@gaearon in #9933)
  • Remove unnecessary dependency from react-linked-input. (@gaearon in #9766)
  • Point react-addons-(css-)transition-group to the new package. (@gaearon in #9937)

What's New in Create React App

May 18, 2017 by Dan Abramov

Less than a year ago, we introduced Create React App as an officially supported way to create apps with zero configuration. The project has since enjoyed tremendous growth, with over 950 commits by more than 250 contributors.

Today, we are excited to announce that many features that have been in the pipeline for the last few months are finally released.

As usual with Create React App, you can enjoy these improvements in your existing non-ejected apps by updating a single dependency and following our migration instructions.

Newly created apps will get these improvements automatically.

webpack 2

This change was contributed by @Timer in #1291.

We have upgraded to webpack 2 which has been officially released a few months ago. It is a big upgrade with many bugfixes and general improvements. We have been testing it for a while, and now consider it stable enough to recommend it to everyone.

While the Webpack configuration format has changed, Create React App users who didn't eject don't need to worry about it as we have updated the configuration on our side.

If you had to eject your app for one reason or another, Webpack provides a configuration migration guide that you can follow to update your apps. Note that with each release of Create React App, we are working to support more use cases out of the box so that you don't have to eject in the future.

The biggest notable webpack 2 feature is the ability to write and import ES6 modules directly without compiling them to CommonJS. This shouldn’t affect how you write code since you likely already use import and export statements, but it will help catch more mistakes like missing named exports at compile time:

Export validation

In the future, as the ecosystem around ES6 modules matures, you can expect more improvements to your app's bundle size thanks to tree shaking.

 Runtime Error Overlay

This change was contributed by @Timer and @nicinabox in #1101, @bvaughn in #2201.

Have you ever made a mistake in code and only realized it after the console is flooded with cryptic errors? Or worse, have you ever shipped an app with crashes in production because you accidentally missed an error in development?

To address these issues, we are introducing an overlay that pops up whenever there is an uncaught error in your application. It only appears in development, and you can dismiss it by pressing Escape.

A GIF is worth a thousand words:

Runtime error overlay

(Yes, it integrates with your editor!)

In the future, we plan to teach the runtime error overlay to understand more about your React app. For example, after React 16 we plan to show React component stacks in addition to the JavaScript stacks when an error is thrown.

Progressive Web Apps by Default

This change was contributed by @jeffposnick in #1728.

Newly created projects are built as Progressive Web Apps by default. This means that they employ service workers with an offline-first caching strategy to minimize the time it takes to serve the app to the users who visit it again. You can opt out of this behavior, but we recommend it both for new and existing apps, especially if you target mobile devices.

Loading assets from service worker

New apps automatically have these features, but you can easily convert an existing project to a Progressive Web App by following our migration guide.

We will be adding more documentation on this topic in the coming weeks. Please feel free to ask any questions on the issue tracker!

Jest 20

This change was contributed by @rogeliog in #1614 and @gaearon in #2171.

We are now using the latest version of Jest that includes numerous bugfixes and improvements. You can read more about the changes in Jest 19 and Jest 20 blog posts.

Highlights include a new immersive watch mode, a better snapshot format, improvements to printing skipped tests, and new testing APIs.

Immersive test watcher

Additionally, Create React App now support configuring a few Jest options related to coverage reporting.

Code Splitting with Dynamic import()

This change was contributed by @Timer in #1538 and @tharakawj in #1801.

It is important to keep the initial JavaScript payload of web apps down to the minimum, and load the rest of the code on demand. Although Create React App supported code splitting using require.ensure() since the first release, it used a webpack-specific syntax that did not work in Jest or other environments.

In this release, we are adding support for the dynamic import() proposal which aligns with the future web standards. Unlike require.ensure(), it doesn't break Jest tests, and should eventually become a part of JavaScript. We encourage you to use import() to delay loading the code for non-critical component subtrees until you need to render them.

Creating chunks with dynamic import

Better Console Output

This change was contributed by @gaearon in #2120, #2125, and #2161.

We have improved the console output across the board.

For example, when you start the development server, we now display the LAN address in additional to the localhost address so that you can quickly access the app from a mobile device on the same network:

Better console output

When lint errors are reported, we no longer show the warnings so that you can concentrate on more critical issues. Errors and warnings in the production build output are better formatted, and the build error overlay font size now matches the browser font size more closely.

But Wait... There's More!

You can only fit so much in a blog post, but there are other long-requested features in this release, such as environment-specific and local .env files, a lint rule against confusingly named globals, support for multiple proxies in development, a customizable browser launch script, and many bugfixes.

You can read the full changelog and the migration guide in the v1.0.0 release notes.


This release is a result of months of work from many people in the React community. It is focused on improving both developer and end user experience, as we believe they are complementary and go hand in hand.

We are grateful to everyone who has offered their contributions, whether in code, documentation, or by helping other people. We would like to specifically thank Joe Haddad for his invaluable help maintaining the project.

We are excited to bring these improvements to everybody using Create React App, and we are looking forward to more of your feedback and contributions.

React v15.5.0

April 7, 2017 by Andrew Clark

It's been exactly one year since the last breaking change to React. Our next major release, React 16, will include some exciting improvements, including a complete rewrite of React's internals. We take stability seriously, and are committed to bringing those improvements to all of our users with minimal effort.

To that end, today we're releasing React 15.5.0.

New Deprecation Warnings

The biggest change is that we've extracted React.PropTypes and React.createClass into their own packages. Both are still accessible via the main React object, but using either will log a one-time deprecation warning to the console when in development mode. This will enable future code size optimizations.

These warnings will not affect the behavior of your application. However, we realize they may cause some frustration, particularly if you use a testing framework that treats console.error as a failure.

Adding new warnings is not something we do lightly. Warnings in React are not mere suggestions — they are integral to our strategy of keeping as many people as possible on the latest version of React. We never add warnings without providing an incremental path forward.

So while the warnings may cause frustration in the short-term, we believe prodding developers to migrate their codebases now prevents greater frustration in the future. Proactively fixing warnings ensures you are prepared for the next major release. If your app produces zero warnings in 15.5, it should continue to work in 16 without any changes.

For each of these new deprecations, we've provided a codemod to automatically migrate your code. They are available as part of the react-codemod project.

Migrating from React.PropTypes

Prop types are a feature for runtime validation of props during development. We've extracted the built-in prop types to a separate package to reflect the fact that not everybody uses them.

In 15.5, instead of accessing PropTypes from the main React object, install the prop-types package and import them from there:

// Before (15.4 and below)
import React from 'react';

class Component extends React.Component {
  render() {
    return <div>{this.props.text}</div>;

Component.propTypes = {
  text: React.PropTypes.string.isRequired,

// After (15.5)
import React from 'react';
import PropTypes from 'prop-types';

class Component extends React.Component {
  render() {
    return <div>{this.props.text}</div>;

Component.propTypes = {
  text: PropTypes.string.isRequired,

The codemod for this change performs this conversion automatically. Basic usage:

jscodeshift -t react-codemod/transforms/React-PropTypes-to-prop-types.js <path>

The propTypes, contextTypes, and childContextTypes APIs will work exactly as before. The only change is that the built-in validators now live in a separate package.

You may also consider using Flow to statically type check your JavaScript code, including React components.

Migrating from React.createClass

When React was initially released, there was no idiomatic way to create classes in JavaScript, so we provided our own: React.createClass.

Later, classes were added to the language as part of ES2015, so we added the ability to create React components using JavaScript classes. Along with functional components, JavaScript classes are now the preferred way to create components in React.

For your existing createClass components, we recommend that you migrate them to JavaScript classes. However, if you have components that rely on mixins, converting to classes may not be immediately feasible. If so, create-react-class is available on npm as a drop-in replacement:

// Before (15.4 and below)
var React = require('react');

var Component = React.createClass({
  mixins: [MixinA],
  render() {
    return <Child />;

// After (15.5)
var React = require('react');
var createReactClass = require('create-react-class');

var Component = createReactClass({
  mixins: [MixinA],
  render() {
    return <Child />;

Your components will continue to work the same as they did before.

The codemod for this change attempts to convert a createClass component to a JavaScript class, with a fallback to create-react-class if necessary. It has converted thousands of components internally at Facebook.

Basic usage:

jscodeshift -t react-codemod/transforms/class.js path/to/components

Discontinuing support for React Addons

We're discontinuing active maintenance of React Addons packages. In truth, most of these packages haven't been actively maintained in a long time. They will continue to work indefinitely, but we recommend migrating away as soon as you can to prevent future breakages.

  • react-addons-create-fragment – React 16 will have first-class support for fragments, at which point this package won't be necessary. We recommend using arrays of keyed elements instead.
  • react-addons-css-transition-group - Use react-transition-group/CSSTransitionGroup instead. Version 1.1.1 provides a drop-in replacement.
  • react-addons-linked-state-mixin - Explicitly set the value and onChange handler instead.
  • react-addons-pure-render-mixin - Use React.PureComponent instead.
  • react-addons-shallow-compare - Use React.PureComponent instead.
  • react-addons-transition-group - Use react-transition-group/TransitionGroup instead. Version 1.1.1 provides a drop-in replacement.
  • react-addons-update - Use immutability-helper instead, a drop-in replacement.
  • react-linked-input - Explicitly set the value and onChange handler instead.

We're also discontinuing support for the react-with-addons UMD build. It will be removed in React 16.

React Test Utils

Currently, the React Test Utils live inside react-addons-test-utils. As of 15.5, we're deprecating that package and moving them to react-dom/test-utils instead:

// Before (15.4 and below)
import TestUtils from 'react-addons-test-utils';

// After (15.5)
import TestUtils from 'react-dom/test-utils';

This reflects the fact that what we call the Test Utils are really a set of APIs that wrap the DOM renderer.

The exception is shallow rendering, which is not DOM-specific. The shallow renderer has been moved to react-test-renderer/shallow.

// Before (15.4 and below)
import { createRenderer } from 'react-addons-test-utils';

// After (15.5)
import { createRenderer } from 'react-test-renderer/shallow';


A special thank you to these folks for transferring ownership of npm package names:


We recommend using Yarn or npm for managing front-end dependencies. If you're new to package managers, the Yarn documentation is a good place to get started.

To install React with Yarn, run:

yarn add react@^15.5.0 react-dom@^15.5.0

To install React with npm, run:

npm install --save react@^15.5.0 react-dom@^15.5.0

We recommend using a bundler like webpack or Browserify so you can write modular code and bundle it together into small packages to optimize load time.

Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, make sure to compile it in production mode.

In case you don't use a bundler, we also provide pre-built bundles in the npm packages which you can include as script tags on your page:

We've also published version 15.5.0 of the react, react-dom, and addons packages on npm and the react package on bower.


15.5.0 (April 7, 2017)


  • Added a deprecation warning for React.createClass. Points users to create-react-class instead. (@acdlite in d9a4fa4)
  • Added a deprecation warning for React.PropTypes. Points users to prop-types instead. (@acdlite in 043845c)
  • Fixed an issue when using ReactDOM together with ReactDOMServer. (@wacii in #9005)
  • Fixed issue with Closure Compiler. (@anmonteiro in #8895)
  • Another fix for Closure Compiler. (@Shastel in #8882)
  • Added component stack info to invalid element type warning. (@n3tr in #8495)

React DOM

  • Fixed Chrome bug when backspacing in number inputs. (@nhunzaker in #7359)
  • Added react-dom/test-utils, which exports the React Test Utils. (@bvaughn)

React Test Renderer

  • Fixed bug where componentWillUnmount was not called for children. (@gre in #8512)
  • Added react-test-renderer/shallow, which exports the shallow renderer. (@bvaughn)

React Addons

  • Last release for addons; they will no longer be actively maintained.
  • Removed peerDependencies so that addons continue to work indefinitely. (@acdlite and @bvaughn in 8a06cd7 and 67a8db3)
  • Updated to remove references to React.createClass and React.PropTypes (@acdlite in 12a96b9)
  • react-addons-test-utils is deprecated. Use react-dom/test-utils and react-test-renderer/shallow instead. (@bvaughn)

React v15.4.0

November 16, 2016 by Dan Abramov

Today we are releasing React 15.4.0.

We didn't announce the previous minor releases on the blog because most of the changes were bug fixes. However, 15.4.0 is a special release, and we would like to highlight a few notable changes in it.

Separating React and React DOM

More than a year ago, we started separating React and React DOM into separate packages. We deprecated React.render() in favor of ReactDOM.render() in React 0.14, and removed DOM-specific APIs from React completely in React 15. However, the React DOM implementation still secretly lived inside the React package.

In React 15.4.0, we are finally moving React DOM implementation to the React DOM package. The React package will now contain only the renderer-agnostic code such as React.Component and React.createElement().

This solves a few long-standing issues, such as errors when you import React DOM in the same file as the snapshot testing renderer.

If you only use the official and documented React APIs you won't need to change anything in your application.

However, there is a possibility that you imported private APIs from react/lib/*, or that a package you rely on might use them. We would like to remind you that this was never supported, and that your apps should not rely on internal APIs. The React internals will keep changing as we work to make React better.

Another thing to watch out for is that React DOM Server is now about the same size as React DOM since it contains its own copy of the React reconciler. We don't recommend using React DOM Server on the client in most cases.

Profiling Components with Chrome Timeline

You can now visualize React components in the Chrome Timeline. This lets you see which components exactly get mounted, updated, and unmounted, how much time they take relative to each other.

React components in Chrome timeline

To use it:

  1. Load your app with ?react_perf in the query string (for example, http://localhost:3000/?react_perf).

  2. Open the Chrome DevTools Timeline tab and press Record.

  3. Perform the actions you want to profile. Don't record more than 20 seconds or Chrome might hang.

  4. Stop recording.

  5. React events will be grouped under the User Timing label.

Note that the numbers are relative so components will render faster in production. Still, this should help you realize when unrelated UI gets updated by mistake, and how deep and how often your UI updates occur.

Currently Chrome, Edge, and IE are the only browsers supporting this feature, but we use the standard User Timing API so we expect more browsers to add support for it.

Mocking Refs for Snapshot Testing

If you're using Jest snapshot testing, you might have had issues with components that rely on refs. With React 15.4.0, we introduce a way to provide mock refs to the test renderer. For example, consider this component using a ref in componentDidMount:

import React from 'react';

export default class MyInput extends React.Component {
  componentDidMount() {

  render() {
    return (
        ref={node => this.input = node}

With snapshot renderer, this.input will be null because there is no DOM. React 15.4.0 lets us avoid such crashes by passing a custom createNodeMock function to the snapshot renderer in an options argument:

import React from 'react';
import MyInput from './MyInput';
import renderer from 'react-test-renderer';

function createNodeMock(element) {
  if (element.type === 'input') {
    return {
      focus() {},
  return null;

it('renders correctly', () => {
  const options = {createNodeMock};
  const tree = renderer.create(<MyInput />, options);

We would like to thank Brandon Dail for implementing this feature.

You can learn more about snapshot testing in this Jest blog post.


We recommend using Yarn or npm for managing front-end dependencies. If you're new to package managers, the Yarn documentation is a good place to get started.

To install React with Yarn, run:

yarn add react@15.4.0 react-dom@15.4.0

To install React with npm, run:

npm install --save react@15.4.0 react-dom@15.4.0

We recommend using a bundler like webpack or Browserify so you can write modular code and bundle it together into small packages to optimize load time.

Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, make sure to compile it in production mode.

In case you don't use a bundler, we also provide pre-built bundles in the npm packages which you can include as script tags on your page:

We've also published version 15.4.0 of the react, react-dom, and addons packages on npm and the react package on bower.



  • React package and browser build no longer "secretly" includes React DOM.
    (@sebmarkbage in #7164 and #7168)
  • Required PropTypes now fail with specific messages for null and undefined.
    (@chenglou in #7291)
  • Improved development performance by freezing children instead of copying.
    (@keyanzhang in #7455)

React DOM

  • Fixed occasional test failures when React DOM is used together with shallow renderer.
    (@goatslacker in #8097)
  • Added a warning for invalid aria- attributes.
    (@jessebeach in #7744)
  • Added a warning for using autofocus rather than autoFocus.
    (@hkal in #7694)
  • Removed an unnecessary warning about polyfilling String.prototype.split.
    (@nhunzaker in #7629)
  • Clarified the warning about not calling PropTypes manually.
    (@jedwards1211 in #7777)
  • The unstable batchedUpdates API now passes the wrapped function's return value through.
    (@bgnorlov in #7444)
  • Fixed a bug with updating text in IE 8.
    (@mnpenner in #7832)

React Perf

  • When ReactPerf is started, you can now view the relative time spent in components as a chart in Chrome Timeline.
    (@gaearon in #7549)

React Test Utils

  • If you call on a <input disabled onClick={foo} /> then foo will get called whereas it didn't before.
    (@nhunzaker in #7642)

React Test Renderer

  • Due to packaging changes, it no longer crashes when imported together with React DOM in the same file.
    (@sebmarkbage in #7164 and #7168)
  • ReactTestRenderer.create() now accepts {createNodeMock: element => mock} as an optional argument so you can mock refs with snapshot testing.
    (@Aweary in #7649 and #8261)