The React team recently released React 17 (first release candidate), two years after React 16. React 17 strives to ease the migration between future major versions of React by enabling two concurrent versions to coexist. React 17 additionally has a few breaking changes related to the event system and the scheduling.
React’s release note explained the key driver behind React 17:
The React 17 release is […] primarily focused on making it easier to upgrade React itself.
[…] The React 17 release is a key part of our strategy to roll [new React features] out without leaving anyone behind.
In particular, React 17 is a “stepping stone” release that makes it safer to embed a tree managed by one version of React inside a tree managed by a different version of React. […] We’ve postponed other changes until after React 17.
React 17 enables gradual React upgrades: when new versions of React are released, developers will have a choice between migrating their React applications all at once – as was the case with the previous versions of React, or upgrade a part of their application and gradually complete the migration. The latter option may involve lazy loading one of the two React versions, in order not to impact the user experience.
The cohabitation of different React versions is made possible by the changes in the event delegation mechanism. Before React 17, React was registering event handlers at the document
level, detecting which component to call, and handling subsequent event bubbling across the component tree. This meant that two React versions would essentially be concurrently accessing shared DOM state (state of the DOM event handling) with no synchronization mechanism between React’s synthetic events (copy) and the DOM events (source of truth). Thus, it may occur that when one React version cancels the (copy) DOM event propagation (event.stopPropagation()
), that cancellation is not communicated to the other React version (second copy) – which may thus react to the canceled event. It may also occur that the event handlers that are registered at the top level run in an unfortunate order.
React 17 attaches the event handlers at the React version’s root DOM container (rootNode
thereafter):
const rootNode = document.getElementById('root'); ReactDOM.render(<App />, rootNode);
Similarly, React can now interoperate more reliably with other JavaScript libraries that also handle a part of the DOM. As a matter of fact, the change in React’s event propagation mechanism fixes a number of old bugs.
Among other breaking changes, the onScroll
event no longer bubbles, onFocus
and onBlur
events use the native focusin
and focusout
, capture phase events (e.g. onClickCapture
) now use real browser capture phase listeners. The changes reduce the discrepancies between the DOM events and the React synthetic events.
React 17 also brings some scheduling changes for the useEffect
hook. The effect cleanup function, which used to run synchronously in React 16, now runs asynchronously. React 17 additionally executes the cleanup functions in the same order as the effects, according to their position in the tree. The changes in scheduling have led to some component breaking. The release note provides additional details about potential issues and remedies.
Developers can install the release candidate with npm:
npm install react@17.0.0-rc.0 react-dom@17.0.0-rc.0
The release note provides the full list of changes (Changelog) and reviews in more detail the motivations behind the main changes.