diff --git a/content/blog/2018-03-29-react-v-16-4.md b/content/blog/2018-03-29-react-v-16-4.md new file mode 100644 index 000000000..b11569fc9 --- /dev/null +++ b/content/blog/2018-03-29-react-v-16-4.md @@ -0,0 +1,128 @@ +--- +title: "React v16.4.0: Experimental Component Profiler and Bugfixes" +author: [acdlite, bvaughn] +--- + +React 16.4 is a minor release that includes an experimental component profiler, as well as a crucial bugfix for `getDerivedStateFromProps`. + +## `React.unstable_Profiler` + +TODO (@bvaughn) + +## Bugfix for `getDerivedStateFromProps` + +`getDerivedStateFromProps` is now called when either props or state change. Previously, it would not fire for state-only changes (similar to `componentWillReceiveProps`). This was an oversight in the initial implementation that has now been corrected. + +### Why? + +`getDerivedStateFromProps` was designed as an alternative to `componentWillReceiveProps` that is compatible with async rendering. Because props in React are derived from state that lives in a parent component, APIs like `componentWillReceiveProps` that are modelled around "prop change events" don't really make sense, and can't be reliably implemented in React's upcoming asynchronous rendering mode. + +Another way to think about it is that `getDerivedStateFromProps(props, state)` accepts both props and state as input, so we need to re-calculate the derived state whenever either of the inputs change. + +### How Does This Affect Me? + +**Most likely, this doesn't require any changes to your components**. The rare cases where it does matter usually fall into one of two categories: + +### Avoid Side Effects in `getDerivedStateFromProps` + +Like the render method, `getDerivedStateFromProps` should be a pure function of props and state. You should move side-effectful code elsewhere. E.g. Flux dispatches typically belong inside the originating event handler; DOM mutations belong inside `componentDidMount` or `componentDidUpdate`. + +Side effects in `getDerivedStateFromProps` were already disallowed, but since it now fires more often than it used to, the recent change may expose previously undiscovered bugs. + +### Compare Incoming Props to Previous Props When Computing Controlled Values + +The following code will not work. It assumes `getDerivedStateFromProps` only fires on prop changes. But since it now fires for state changes, too, local updates to the controlled value will be ignored, since the props version always overrides it. + +```js +static getDerivedStateFromProps(props, state) { + if (props.value !== state.controlledValue) { + return { + // Props always win. Oops! + controlledValue: props.value, + }; + } + return null; +} +``` + +You can change it to do this instead: + +```js +static getDerivedStateFromProps(props, state) { + const prevProps = state.prevProps; + // Compare incoming props to previous props + const controlledValue = + prevProps.value !== state.controlledValue + ? prevProps.value + : state.controlledValue; + return { + // Store the previous props in state + prevProps: props, + controlledValue, + }; +} +``` + +## Installation + +React v16.4.0 is available on the npm registry. + +To install React 16 with Yarn, run: + +```bash +yarn add react@^16.4.0 react-dom@^16.4.0 +``` + +To install React 16 with npm, run: + +```bash +npm install --save react@^16.4.0 react-dom@^16.4.0 +``` + +We also provide UMD builds of React via a CDN: + +```html + + +``` + +Refer to the documentation for [detailed installation instructions](/docs/installation.html). + +## Changelog + +### React + +* Add a new [experimental](https://github.com/reactjs/rfcs/pull/51) `React.unstable_Profiler` component for measuring performance. ([@bvaughn](https://github.com/bvaughn) in [#12745](https://github.com/facebook/react/pull/12745)) + +### React DOM + +* Add support for the Pointer Events specification. ([@philipp-spiess](https://github.com/philipp-spiess) in [#12507](https://github.com/facebook/react/pull/12507)) +* Properly call `getDerivedStateFromProps()` regardless of the reason for re-rendering. ([@acdlite](https://github.com/acdlite) in [#12600](https://github.com/facebook/react/pull/12600) and [#12802](https://github.com/facebook/react/pull/12802)) +* Fix a bug that prevented context propagation in some cases. ([@gaearon](https://github.com/gaearon) in [#12708](https://github.com/facebook/react/pull/12708)) +* Fix re-rendering of components using `forwardRef()` on a deeper `setState()`. ([@gaearon](https://github.com/gaearon) in [#12690](https://github.com/facebook/react/pull/12690)) +* Fix some attributes incorrectly getting removed from custom element nodes. ([@airamrguez](https://github.com/airamrguez) in [#12702](https://github.com/facebook/react/pull/12702)) +* Fix context providers to not bail out on children if there's a legacy context provider above. ([@gaearon](https://github.com/gaearon) in [#12586](https://github.com/facebook/react/pull/12586)) +* Add the ability to specify `propTypes` on a context provider component. ([@nicolevy](https://github.com/nicolevy) in [#12658](https://github.com/facebook/react/pull/12658)) +* Fix a false positive warning when using `react-lifecycles-compat` in ``. ([@bvaughn](https://github.com/bvaughn) in [#12644](https://github.com/facebook/react/pull/12644)) +* Warn when the `forwardRef()` render function has `propTypes` or `defaultProps`. ([@bvaughn](https://github.com/bvaughn) in [#12644](https://github.com/facebook/react/pull/12644)) +* Improve how `forwardRef()` and context consumers are displayed in the component stack. ([@sophiebits](https://github.com/sophiebits) in [#12777](https://github.com/facebook/react/pull/12777)) +* Change internal event names. This can break third-party packages that rely on React internals in unsupported ways. ([@philipp-spiess](https://github.com/philipp-spiess) in [#12629](https://github.com/facebook/react/pull/12629)) + +### React Test Renderer + +* Fix the `getDerivedStateFromProps()` support to match the new React DOM behavior. ([@koba04](https://github.com/koba04) in [#12676](https://github.com/facebook/react/pull/12676)) +* Fix a `testInstance.parent` crash when the parent is a fragment or another special node. ([@gaearon](https://github.com/gaearon) in [#12813](https://github.com/facebook/react/pull/12813)) +* `forwardRef()` components are now discoverable by the test renderer traversal methods. ([@gaearon](https://github.com/gaearon) in [#12725](https://github.com/facebook/react/pull/12725)) +* Shallow renderer now ignores `setState()` updaters that return `null` or `undefined`. ([@koba04](https://github.com/koba04) in [#12756](https://github.com/facebook/react/pull/12756)) + +### React ART + +* Fix reading context provided from the tree managed by React DOM. ([@acdlite](https://github.com/acdlite) in [#12779](https://github.com/facebook/react/pull/12779)) + +### React Call Return (Experimental) + +* This experiment was deleted because it was affecting the bundle size and the API wasn't good enough. It's likely to come back in the future in some other form. ([@gaearon](https://github.com/gaearon) in [#12820](https://github.com/facebook/react/pull/12820)) + +### React Reconciler (Experimental) + +* The [new host config shape](https://github.com/facebook/react/blob/c601f7a64640290af85c9f0e33c78480656b46bc/packages/react-noop-renderer/src/createReactNoop.js#L82-L285) is flat and doesn't use nested objects. ([@gaearon](https://github.com/gaearon) in [#12792](https://github.com/facebook/react/pull/12792))