Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

React 17.0.0-rc.2 is officially released, introducing a new JSX transformation


May 31, 2021 Article blog


Table of contents


In the early hours of September 23, Beijing time, the React team released a blog about the new JSX transformation, along with a version of React 17.0.0-rc.2, which no longer relies on the React environment and automatically introduces a new runtime when converting.

Original link: reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html

By Luna Ruan

Translator: QC-L

Launched on react Chinese documentation blog, you're welcome to follow https://zh-hans.reactjs.org or follow the imprint Chinese public number.

Although React 17 does not include the new feature , it will provide a completely new version of the JSX conversion. In this article, we'll describe what it is and how to use it.

What is a JSX conversion?

JSX is not available directly in the browser, so most React developers rely on Babel or TypeScript to convert JSX code to JavaScript. Many preconfigured tools, such as the Create React app or Next .js, also introduce JSX transformations internally.

React 17 was released immediately, and while we wanted to improve the JSX transformation, we didn't want to break the existing configuration. So we chose to partner with Babel to provide a completely new version of the reconfigured JSX transformation for developers who want to upgrade.

Upgrading to a brand new conversion is entirely optional, but upgrading will bring you some benefits:

  • With the new transformation, you can use JSX alone without introducing React.
  • Depending on your configuration, JSX's compilation output may slightly improve the size of the bundle.
  • It will reduce the number of react concepts you need to learn in case of future needs.

This upgrade does not change the JSX syntax and is not required. The old JSX transformation will continue to work and there are no plans to unblock it.

The RC version of React 17 has introduced support for the new transform, so you can give it a try! T o make it easier for everyone to use, we also plan to support React 16.x, React 15.x, and React 0.14x after React 17 is officially released. You can find upgrade instructions for different environments in the

Next, let's carefully compare the differences between old and new transformations.

What's the difference between the new transformations?

When you use JSX, the compiler converts it to a react function call that the browser can understand. The old JSX conversion converts the JSX to React.createElement(...) call.

For example, suppose the source code is as follows:

import React from 'react';


function App() {
  return <h1>Hello World</h1>;
}

The old JSX conversion turns the above code into plain JavaScript code:

import React from 'react';


function App() {
  return React.createElement('h1', null, 'Hello world');
}

note

There is no need to change the source code. We'll show you how JSX transformation turns your JSX source code into JavaScript code that your browser can understand.

However, this is not perfect:

  • If you use JSX, you need to be in React environment because JSX will be compiled into React.createElement
  • There are some performance optimizations and simplifications that React.createElement can't do.

To address these issues, React 17 introduced two new portals in React's package that will only be used by compilers such as Babel and TypeScript. T he new JSX transformation does not convert JSX to React.createElement but automatically introduces new entry functions and calls them from React's package. For example:

function App() {
  return <h1>Hello World</h1>;
}

The conversion will now be to:

// 由编译器引入(禁止自己引入!)
import {jsx as _jsx} from 'react/jsx-runtime';


function App() {
  return _jsx('h1', { children: 'Hello world' });
}

Note that at this point the source code does not need to be introduced to React to use JSX! ( However, You Still Need To Introduce React To Use The Hook Or Other ExportS ProvideD By React.)

This change is compatible with all existing JSX code, so you don't need to modify the component. If you're interested in this, you can check out RFC for details of the new conversion effort.

note

Functions in react/jsx-runtime and react/jsx-dev-runtime can only be used by compiler conversions. I f you need to create elements manually in your code, you can continue to use React.createElement It will continue to work and will not go away.

How to upgrade to a new conversion

If you're not ready to upgrade to a brand new JSX transformation, or if you're using JSX for another library, don't worry that the old conversion won't be removed and will continue to be supported.

If you want to upgrade, you need to prepare two things:

  • The newly converted React version is supported (currently, only RC version of React 17 supports it, but after React 17.0 is released, we plan to be compatible with 0.14.x, 15.x, and 16.x.).
  • A compiler compatible with the new conversion (see the instructions below for the different tools).

Since the new JSX transformation does not depend on the React environment, we have prepared an automated script to remove unnecessary ingestions from your code.

Create React App

The React Create app is already compatible with it and will be available in the upcoming v4.0 release, which is in beta.

Next.js

Next.js's v9.5.3 is compatible with the React version with the new conversion.

Gatsby

Gatsby's v2.24.5 will use the new conversion to be compatible with the React version.

note

If you encounter error in Gatsby, upgrade to 17.0.0-rc.2 and run npm update to resolve the issue.

Configure Babel manually

Babel's v7.9.0 (14) and above versions support the new JSX conversion.

First, you need to update to the latest version of the Babel and transform plug-ins.

If you are using @babel/plugin-transform-react-jsx :

# npm 用户
npm update @babel/core @babel/plugin-transform-react-jsx
# yarn 用户
yarn upgrade @babel/core @babel/plugin-transform-react-jsx

If you are using @babel/preset-react :

# npm 用户
npm update @babel/core @babel/preset-react
# yarn 用户
yarn upgrade @babel/core @babel/preset-react

Currently, the default option for the old conversion is "runtime": "classic" To enable the new conversion, you can use {"runtime": "automatic"} option @babel/plugin-transform-react-jsx or @babel/preset-react

// 如果你使用的是 @babel/preset-react
{
  "presets": [
    ["@babel/preset-react", {
      "runtime": "automatic"
    }]
  ]
}
// 如果你使用的是 @babel/plugin-transform-react-jsx
{
  "plugins": [
    ["@babel/plugin-transform-react-jsx", {
      "runtime": "automatic"
    }]
  ]
}

Starting with Babel 8, "automatic" integrates the two plug-ins into rumtime by default. For more information, please refer to the @babel/plugin-transform-react-jsx and @babel/preset-react in the Babel documentation.

note

If you're using a library other than React when you're using JSX, you can introduce it from that library using the importSource option , provided it provides the necessary entry points. Or you can continue to use the classic conversion, which will continue to be supported.

ESLint

If you are using eslint-plugin-react, where react/jsx-uses-react and react/react-in-jsx-scope will no longer be needed, you can close them or delete them.

{
  // ...
  "rules": {
    // ...
    "react/jsx-uses-react": "off",
    "react/react-in-jsx-scope": "off"
  }
}

TypeScript

TypeScript will support the new JSX conversion in the v4.1 beta version.

Flow

Flow will support the new JSX transformation in v0.126.0 .

Remove unused React ingestions

Because the new JSX transformation automatically introduces the necessary react/jsx-runtime when you use JSX, there is no need to introduce React. T his may result in an unused React introduction in your code. It doesn't hurt to keep them, but if you want to delete them, we recommend running a "codemod" script to automatically delete them:

cd your_project
npx react-codemod update-react-imports

note:

If you get an error running codemod, try using npx react-codemod update-react-imports select a different JavaScript environment. E specially when you choose JavaScript with Flow, you can choose it even if you're not using Flow because it supports newer syntax than JavaScript. If you're having trouble, please let us know.

Note that codemod's output may not match your code style, so you may need to perform Prettier after codemod is complete to ensure that the format is the same.

Running codemod does the following:

  • Upgrade to a new JSX transformation and remove all unused React ingestions.
  • Changing the default introduction of all Reacts will be replaced by deconstructing the naming introduction (for example, import React from "react" will become import { useState } from "react" which will be the preferred style for future development. Codemod does not affect the way namespaces are introduced (i.e., import as React from import * as React from "react" which is also a valid style, and the default introduction will continue to work in React 17, but in the long run we recommend that you try not to use them.

example:

import React from 'react';


function App() {
  return <h1>Hello World</h1>;
}

will be replaced by

function App() {
  return <h1>Hello World</h1>;
}

If you use react's other exports, such as Hook, codemod converts them to named imports.

example:

import React from 'react';


function App() {
  const [text, useText] = React.useState('Hello World');
  return <h1>{text}</h1>;
}

will be replaced

import { useState } from 'react';


function App() {
  const [text, useText] = useState('Hello World');
  return <h1>{text}</h1>;
}

In addition to cleaning up unused ingestions, this tool can also help you pave the way for future major versions of React (not React 17), which will support ES modules and do not export by default.

Acknowledgement

We would like to thank Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, and Flow's key maintainers for the implementation and integration of the new JSX transformation. We would also like to thank the React community for their feedback and discussions on the relevant RFC.

Resources

The new feature is not included: /blog/2020/08/10/react-v17-rc.html

[2] Babel: https://babeljs.io/blog/2020/03/16/7.9.0#a-new-jsx-transform-11154httpsgithubcombabelbabelpull11154

[3] RC version of React 17: /blog/2020/08/10/react-v17-rc.html

Below: #how-to-upgrade-to-the-new-jsx-transform

Performance optimization and simplification: https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md#motivation

[6] RFC: https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md#detailed-design

[7] RC version of React 17: /blog/2020/08/10/react-v17-rc.html

We have prepared an automatic script: #removing-unused-react-imports

Compatibility support for it: https://github.com/facebook/create-react-app/pull/9645

Upcoming v4.0 release: https://gist.github.com/iansu/282dbe3d722bd7231fa3224c0f403fa1

[11]v9.5.3: https://github.com/vercel/next.js/releases/tag/v9.5.3

[12]v2.24.5: https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/CHANGELOG.md#22452-2020-08-28

[13] Error: https://github.com/gatsbyjs/gatsby/issues/26979 encountered in Gatsby

[14]v7.9.0: https://babeljs.io/blog/2020/03/16/7.9.0

[15]@babel/plugin-transform-react-jsx: https://babeljs.io/docs/en/babel-plugin-transform-react-jsx

[16]@babel/preset-react: https://babeljs.io/docs/en/babel-preset-react

[17] importSource option: https://babeljs.io/docs/en/babel-preset-react#importsource

[18]eslint-plugin-react: https://github.com/yannickcr/eslint-plugin-react

[19]v4.1 beta: https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#jsx-factories

[20]v0.126.0: https://github.com/facebook/flow/releases/tag/v0.126.0

[21]“codemod”: medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb

Let us know: https://github.com/reactjs/react-codemod/issues

[23] Prettier: https://prettier.io/

[24] RFC: https://github.com/reactjs/rfcs/pull/107

That's W3Cschool编程狮 has to say about the official release of React 17.0.0-rc.2, introducing a new JSX transformation.