2 min read

React 17 - Upgrade Summary


Josip Blažević




React 17 - Upgrade Summary banner

React 17 is an update that does not bring any new features, but instead it modifies the existing ones. This update is focused on making React easier to upgrade in the future. Upgrading from version 16 to 17 can usually be made without breaking any of the existing features.

React Native supports React 17 from version 0.64.

Gradual Upgrades

Until now, if you wanted to upgrade React, you would need to upgrade it all at once. This could lead to many compatibility issues.

Although it is still preferred way to update React as a whole, now you can update it in parts.

It is done by adding legacy, modern and shared folders in your project src folder.

  • legacy contains components which use an older version of React
  • modern contains components which use an updated version of React
  • shared contains components which are used in both versions of React

For this to work, you would need three different package.json files.

The main package.json is placed in the root folder and includes everything besides react.

src/legacy/package.json contains legacy react and react-dom.

src/modern/package.json contains updated react and react-dom.

Specific package.json files can also include third-party libraries if the specific React version is required for them to work.

Find out more about this topic on the official blog post.

Also here is the example demo.

Event Delegation

This is a potentially breaking change if your event logic depends on the events that need to strictly be added to your document root.

Using document object no longer adds event handlers to the document root, but instead to the React root div element.

Event delegation drawing

If you need more details about this topic you can look them up on the official blog post.

New JSX Transform

New JSX transform is completely optional, but it comes with its own benefits.

  • • JSX can now be used without importing React in your files
  • • It may slightly improve the project bundle size
  • • It will enable future improvements that reduce the number of concepts to learn React

JSX syntax will not be changed in any way.

Under the Hood

import React from 'react'; function App() { return <h1>Hello World</h1>; } // Under the hood, the old JSX transform is transformed into regular JS code import React from 'react'; function App() { return React.createElement('h1', null, 'Hello world'); }

Since JSX was compiled into React.createElement, React needed to be imported into scope.

Also there are some performance improvements and code simplifications with the new transform.

The new transform can be preformed by compilers like Babel and TypeScript.

function App() { return <h1>Hello World</h1>; } // Under the hood, new JSX transform // Inserted by a compiler (don't import it yourself!) import {jsx as _jsx} from 'react/jsx-runtime'; function App() { return _jsx('h1', { children: 'Hello world' }); } You can learn more about new JSX transform in the official blog post.

useEffect Cleanup Timing

In earlier React versions, useEffect cleanup was synchronous function, but it is currently changed to asynchronous function to improve performance by reducing delays on screen updates. Cleanup now runs after the screen has been updated.

useEffect(() => { // This is the effect itself. return () => { // This is its cleanup. }; }); Read more about this topic on the official blog post.

No Event pooling

React 17 removes event pooling optimization since it did not improve performance in the earlier versions. You no longer need to use event.persist() to have persistent events.

event.persist() function is not removed, but it does not have any effect now.

Read more about this topic on the official blog post.

Consistent Errors for Returning Undefined

Returning undefined is usually an unintentional behavior. Returning undefined throws an error as it is most likely a coding mistake. In earlier versions React threw an error only for function and class components, but now, returning undefined from forwardRef and useMemo also throws an error.

let Button = forwardRef(() => { // React 17 surfaces this as an error instead of ignoring it. <button />; }); let Button = useMemo(() => { // React 17 surfaces this as an error instead of ignoring it. <button />; }); Read more about this topic on the official blog post.

Other Changes

  • • Private exports are removed
  • • onScroll event no longer bubbles
  • • React onFocus and onBlur events use native focusin and focusout events
  • • Capture phase events (e.g. onClickCapture) now use real browser capture phase listeners.
You can look up full changelog on the official React blog.