Wording changes for update-on-async and strict-mode
Incorporates most of Sophie's feedback.
Changes update-on-async references to 16.3 to be future tense (since this blog post will be released before 16.3). Changes strict-mode references to be past-tense (since this will be a docs page instead of a blog post).
`StrictMode` is a tool for highlighting potential problems in an application. Like `Fragment`, `StrictMode` does not render any visible UI. It simply activates additional checks and warnings for its descendants.
`StrictMode` is a tool for highlighting potential problems in an application. Like `Fragment`, `StrictMode` does not render any visible UI. It activates additional checks and warnings for its descendants.
> Note:
>
@ -12,9 +12,9 @@ author: [bvaughn]
You can enable strict mode for any part of your application. For example:
In the above example, strict mode checks will *not* be run against the `Header` and `Footer` components. However, `RouteOne` and `RouteTwo`, as well as all of their descendants, will have the checks.
In the above example, strict mode checks will *not* be run against the `Header` and `Footer` components. However, `ComponentOne` and `ComponentTwo`, as well as all of their descendants, will have the checks.
In version 16.3, `StrictMode` helps with:
`StrictMode` currently helps with:
* [Identifying components with unsafe lifecycles](#identifying-unsafe-lifecycles)
* [Warning about legacy string ref API usage](#warning-about-legacy-string-ref-api-usage)
* [Detecting unexpected side effects](#detecting-unexpected-side-effects)
@ -35,24 +35,24 @@ Addressing the issues identified by strict mode _now_ will make it easier for yo
Previously, React provided two ways for managing refs: the legacy string ref API and the callback API. Although the string ref API was the more convenient of the two, it had [several downsides](https://github.com/facebook/react/issues/1373) and so our official recomendation was to [use the callback form instead](https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs).
Version 16.3 adds a new option for managing refs that offers the convenience of a string ref without any of the downsides:
React 16.3 added a third option that offers the convenience of a string ref without any of the downsides:
`embed:16-3-release-blog-create-ref.js`
Since object refs were largely added as a replacement for string refs, strict mode now warns about usage of string refs.
> **Note:**
>
> Callback refs will continue to be supported in addition to the new `createRef` API.
>
> You don't need to replace callback refs in your components. They are slightly more flexible, so they will remain as an advanced feature.
Since object refs were largely added as a replacement for string refs, strict mode now warns about usage of string refs.
[Learn more about the new `createRef` API here.](#)
[Learn more about the new `createRef` API here.](/docs/refs-and-the-dom.html)
### Detecting unexpected side effects
Conceptually, React does work in two phases:
* The **render** phase determines what changes need to be made to e.g. the DOM. During this phase, React calls `render` and then compares the result to the previous render.
* The **commit** phase is when React applies any changes. (In the case of ReactDOM, this is when React inserts, updates, and removes DOM nodes.) React also calls lifecycles like `componentDidMount` and `componentDidUpdate` during this phase.
* The **commit** phase is when React applies any changes. (In the case of ReactDOM, this is when React inserts, updates, and removes DOM nodes.) React also calls lifecycles like `componentDidMount` and `componentDidUpdate` during this phase.
The commit phase is usually very fast, but rendering can be slow. For this reason, the upcoming async mode (which is not enabled by default yet) breaks rendering into multiple pieces, pausing and resuming the work to avoid blocking the browser. This means that React may invoke render phase lifecycles more than once before committing, or it may invoke them without committing at all (because of an error or a higher priority interruption).
@ -66,7 +66,7 @@ Render phase lifecycles include the following class component methods:
* `render`
* `setState` updater functions (the first argument)
Because the above methods might be called more than once, it's important that they do not contain side-effects. Ignoring this rule can lead to a variety of problems, including memory leaks and invalid application state. Unfortunately, it can be difficult to detect these problems as they are often [non-deterministic](https://en.wikipedia.org/wiki/Deterministic_algorithm).
Because the above methods might be called more than once, it's important that they do not contain side-effects. Ignoring this rule can lead to a variety of problems, including memory leaks and invalid application state. Unfortunately, it can be difficult to detect these problems as they can often be [non-deterministic](https://en.wikipedia.org/wiki/Deterministic_algorithm).
Strict mode can't automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following methods:
For the past few months, the React team has been experimenting with [asynchronous rendering](/blog/2017/09/26/react-v16.0.html#new-core-architecture), and we are very excited about the new features it enables.
Along the way, our research has shown that some of our legacy component lifecycles tend to encourage unsafe coding practices. They are:
Along the way, our research has shown that some of our component lifecycles tend to encourage unsafe coding practices. They are:
* `componentWillMount`
* `componentWillReceiveProps`
* `componentWillUpdate`
Because of this, we are adding an "UNSAFE_" prefix to these lifecycles in a future release. React [follows semantic versioning](/blog/2016/02/19/new-versioning-scheme.html), so the migration path will be gradual:
These lifecycle methods have often been misunderstood and subtly misused; furthermore, we anticipate that these potential problems may be more prominent with async rendering. Because of this, we are adding an "UNSAFE_" prefix to these lifecycles in a future release. React [follows semantic versioning](/blog/2016/02/19/new-versioning-scheme.html), so the migration path will be gradual:
* **16.3**: Introduce aliases for the unsafe lifecycles, `UNSAFE_componentWillMount`, `UNSAFE_componentWillReceiveProps`, and `UNSAFE_componentWillUpdate`. (Both the old lifecycle names and the new aliases will work in this release.)
* **16.4**: Enable deprecation warning for `componentWillMount`, `componentWillReceiveProps`, and `componentWillUpdate`. (Both the old lifecycle names and the new aliases will work in this release.)
@ -21,17 +21,16 @@ In this post, we will explore some of the potential capabilities of async render
## What can asynchronous rendering do?
#### With every new version, our goal is to improve the user experience of apps created with React.
#### With every new version, our goal is to make it easier for developers using React to build great user experiences
We have been fine-tuning the performance of React with every new release. However, despite what synthetic benchmarks say, we've found that the real bottleneck is generally not React itself, but the application code that uses it. In order to unlock the next wave of performance optimizations and new features, we need React to be smarter about when to re-render components and flush updates to the screen.
We have been fine-tuning the performance of React with every new release. However, despite what synthetic benchmarks say, we've found that the bottleneck in real-world apps is generally not React itself, but the application code that uses it. In order to unlock the next wave of performance optimizations and new features, we need React to be smarter about when to re-render components and flush updates to the screen.
We found that asynchronous rendering can help in several ways. For example:
1. As users navigate within an app, newly displayed components often have asynchronous dependencies (including data, images, and code splitting). This leads to a lot of boilerplate code managing data fetching and displaying the loading states. It can also lead to a "cascade of spinners" as the data loads, causing DOM reflows and janky user experience. We'd like to make it easier for product developers to express asynchronous dependencies of components. React could keep the old UI "alive" and interactive for a certain period while the updated UI is not ready yet, and provide a declarative way to show a loading indicator if it takes more than a second.
1. As users navigate within an app, newly displayed components often have asynchronous dependencies (including data, images, and code splitting). This leads to a lot of boilerplate code managing data fetching and displaying the loading states. It can also lead to a "cascade of spinners" as the data loads, causing DOM reflows and janky user experience. We'd like to make it easier for product developers to express asynchronous dependencies and to wait to show a component until all of its data has been loaded. React could keep the old UI "alive" and interactive for a certain period while the updated UI is not ready yet, and provide a declarative way to show a loading indicator if it takes more than a second.
2. Fast updates within a short timeframe often cause jank because React processes each update individually. We'd like to automatically "combine" updates within a few hundred milliseconds when possible so that there is less re-rendering.
3. Some updates are inherently less important than others. For example, if you're writing a live-updating search filter input like [this](https://zeit.co/blog/domains-search-web#asynchronous-rendering), it is essential that the input is updated immediately (within a few milliseconds). Re-rendering the result list can be done later, and should not block the thread or cause stutter when typing. It would be nice if React had a way to mark the latter updates as having a lower priority. (Note that even debouncing the input doesn't help because if the rendering is synchronous—like in React today—a keystroke can't interrupt the rendering once it has started. Asynchronous rendering solves this by splitting rendering into small chunks that can be paused and later resumed.)
4. For UI elements like hidden popups and tabs, we'd like to be able to start pre-rendering their content when the browser isn't busy. This way, they can appear instantaneously in response to a later user interaction. However, we don't want to make the initial rendering slower, so it's essential to render such elements lazily ([when the browser is idle](https://developers.google.com/web/updates/2015/08/using-requestidlecallback)).
5. For many apps, React is not the only JavaScript on the page. It often has to coordinate with other JS libraries, server-rendered widgets, and so on. Asynchronous rendering lets React better coordinate with non-React code regarding when components are inserted into the DOM so that [the user experience is smooth](https://twitter.com/acdlite/status/909926793536094209).
3. Some updates are inherently less important than others. For example, if you're writing a [live-updating search filter input](https://zeit.co/blog/domains-search-web#asynchronous-rendering), it is essential that the input is updated immediately (within a few milliseconds). Re-rendering the result list can be done later, and should not block the thread or cause stutter when typing. It would be nice if React had a way to mark the latter updates as having a lower priority. (Note that even debouncing the input doesn't help because if the rendering is synchronous (like in React today)—a keystroke can't interrupt the rendering once it has started. Asynchronous rendering solves this by splitting rendering into small chunks that can be paused and later resumed.)
4. For UI elements like hidden popups and tabs, we'd like to be able to start pre-rendering their content when the browser isn't busy. This way, they can appear instantaneously in response to a later user interaction. However, we'd like to do this only [when the browser is idle](https://developers.google.com/web/updates/2015/08/using-requestidlecallback) to avoid slowing down other parts of the page.
Of course, it's possible to implement some of these features today, but it's difficult. We hope to make them effortless by building them into React itself. By replacing problematic lifecycles with safer alternatives, we also hope to make it simple to write async-safe React components.
@ -39,9 +38,28 @@ In the next section, we'll look at how to update your existing components to pre
## Updating class components
#### If you're an application developer, **you don't have to do anything about the legacy methods yet**. The primary purpose of this update (v16.3) is to enable open source project maintainers to update their libraries in advance of any deprecation warnings. Those warnings will be enabled with the next minor release, v16.4.
#### If you're an application developer, **you don't have to do anything about the legacy methods yet**. The primary purpose of the upcoming version 16.3 is to enable open source project maintainers to update their libraries in advance of any deprecation warnings. Those warnings will be enabled with the next minor release, version 16.4.
However, if you'd like to start using the new component API (or if you're a maintainer looking to update your library in advance) here are a few examples that we hope will help you to start thinking about components a bit differently. Over time, we plan to add additional "recipes" to our documentation that show how to perform common tasks in a way that's async-safe.
However, if you'd like to start using the new component API (or if you're a maintainer looking to update your library in advance) here are a few examples that we hope will help you to start thinking about components a bit differently. Over time, we plan to add additional "recipes" to our documentation that show how to perform common tasks in a way that avoids the problematic lifecycles.
---
Before we begin, here's a quick reminder of the lifecyle changes in version 16.3:
* We are adding the following lifecycle aliases: `UNSAFE_componentWillMount`, `UNSAFE_componentWillReceiveProps`, and `UNSAFE_componentWillUpdate`. (Both the old lifecycle names and the new aliases will be supported.)
* We are introducinc a new, static lifecycle, `getDerivedStateFromProps`:
```js
static getDerivedStateFromProps(
nextProps: Props,
prevState: State
): $Shape<State> | null
```
This new lifecycle is invoked after a component is instantiated and when it receives new props. It should return an object to update `state`, or `null` to indicate that the new `props` do not require any `state` updates.
---
Now let's take a look at some examples.
### Initializing state
@ -58,7 +76,7 @@ Here is an example of a component that uses `componentWillMount` to fetch extern
The above code is problematic for both server rendering (where the external data won't be used) and the upcoming async rendering mode (where the request might be initiated multiple times, or executed unnecessarily).
The upgrade path for this is to move data-fetching into `componentDidMount`:
The recommended upgrade path for most use cases is to move data-fetching into `componentDidMount`:
There is a common misconception that fetching in `componentWillMount` lets you avoid the first empty rendering state. In practice this was never true because React has always executed `render` immediately after `componentWillMount`. If the data is not available by the time `componentWillMount` fires, the first `render` will still show a loading state regardless of where you initiate the fetch. This is why moving the fetch to `componentDidMount` has no perceptible effect in the vast majority of cases.
@ -79,6 +97,10 @@ People often assume that `componentWillMount` and `componentWillUnmount` are alw
For this reason, the recommended way to add listeners/subscriptions is to use the `componentDidMount` lifecycle:
> Although the pattern above is slightly more verbose, it has an added benefit of deferring the subscription creation until after the component has rendered, reducing the amount of time in the critical render path. In the near future, React may include more tools to reduce code complexity for data fetching cases like this.
### Updating `state` based on `props`
Here is an example of a component that uses the legacy `componentWillReceiveProps` lifecycle to update `state` based on new `props` values:
@ -86,12 +108,14 @@ Here is an example of a component that uses the legacy `componentWillReceiveProp
Although the above code is not problematic in itself, the `componentWillReceiveProps` lifecycle is often mis-used in ways that _do_ present problems. Because of this, the method has been deprecated.
As of version 16.3, the recommended way to update `state` in response to `props` changes is using the new `static getDerivedStateFromProps` lifecycle:
As of version 16.3, the recommended way to update `state` in response to `props` changes is with the new `static getDerivedStateFromProps` lifecycle. (That lifecycle is called when a component is created and each time it receives new props.):
> The [`react-lifecycles-compat`](https://github.com/reactjs/react-lifecycles-compat) polyfill allows this new lifecycle to be used with older versions of React as well. This can be helpful if you're writing a shared component that is intended for use with multiple versions of React.
>
> This polyfill is not needed for application code that uses a specific version of React. It is only useful for shared components (e.g. open source, NPM packages).
### Invoking external callbacks
@ -113,7 +137,7 @@ Open source maintainers might be wondering what these changes mean for shared co
Fortunately, you do not!
Along with the release of 16.3, we've also released a new NPM package, [`react-lifecycles-compat`](https://github.com/reactjs/react-lifecycles-compat). This package polyfills components so that the new `getDerivedStateFromProps` lifecycle will also work with older versions of React (0.14.9+).
In support of version 16.3, we've also created a new NPM package, [`react-lifecycles-compat`](https://github.com/reactjs/react-lifecycles-compat). This package polyfills components so that the new `getDerivedStateFromProps` lifecycle will also work with older versions of React (0.14.9+).
To use this polyfill, first add it as a dependency to your library: