What is JSX Transformation
Since browsers don't understand JSX out of the box, developers rely on compilers like Babel or Typescript to transform JSX into plain JS. React 17 Release Candidate introduces a new, optional JSX to JS transformation mechanism.
Here are the benefits:
- Using JSX without React Import
- Depending on the settings, the bundle may be slightly smaller
- In the future, features will be available to simplify the work with react
(Maybe I didn't quite translate it accurately - here's the original: It will enable future improvements that reduce the number of concepts you need to learn React ) The
upgrade does not change JSX itself in any way and all compilers worked and will work. There are no plans to abandon them. It is planned to support the new JSX Transform mechanism for older versions of React: 16.x, 15.x, 14.x, here are the instructions for the upgrade.
What changed
The old JSX transformation worked like this:
Code
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
Transformed into
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
But this is not great and here's why:
- Since JSX compiles to React.createElement, React needs to be in scope
- There are several options to improve speed and simplify that React.createElement blocks
To address this, React 17 introduces two new entry points for use by other tools such as Babel and Typescript, and now instead of transforming into React.createElement, new functions from the React package are imported and called.
Let's say your code looked like this:
function App() {
return <h1>Hello World</h1>;
}
After a new transformation, it will look like this:
// 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' });
}
The new mechanism does not import React, although it is still needed for the hooks to work.
The new transformation is fully compatible with all existing JSX code, you don't have to change anything. Here are the technical details of how the new JSX transform works.
How to upgrade
If you are not ready to upgrade or are using JSX for other libraries, do not worry, the old transformation will not be removed and will be supported.
The upgrade requires two things:
- React version with new transformation support. So far it is only 17, but in the future 16.x, 15.x and 14.x
- Compatible compiler (see below)
Create React App
Create React App support will be in v4.0 release now it is in beta testing (as of 09/22/2020)
Next.js
Next.js v9.5.3 + already uses the new React transformation for compatible versions.
Gatsby
Gatsby v2.24.5 + already uses the new React transformation for compatible versions.
Manual Babel Configuration
Support from v7.9.0 and above.
If you are usingbabel/ 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 usebabel/ preset-react:
# npm
npm update @babel/core @babel/preset-react
# yarn
yarn upgrade @babel/core @babel/preset-react
Now for transforming JSX, intobabel/ plugin-transform-react-jsx and in babel/ preset-react, the default is {"runtime": "classic"} this is the old version of the transformation. To enable a new transformation, you need the option {"runtime": "automatic"}
If you usebabel/ preset-react:
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
If you are using babel/ plugin-transform-react-jsx:
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
As of Babel 8, "automatic" will be the default for both plugins. There is more detailed documentation here @ babel / plugin-transform-react-jsx and @ babel / preset-react .
Note
, importSource , . , .
ESLint
If you have the eslint-plugin-react plugin , then the react / jsx-uses-react and react / react-in-jsx-scope rules are no longer needed and can be removed.
{
// ...
"rules": {
// ...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
TypeScript
Support for JSX transformations since version 4.1 beta .
Flow
Support for JSX transformations from version 0.126.0 and higher.
How to strip out unused React imports
Since the new JSX transform will automatically import react / jsx-runtime, React is no longer needed in scope to use JSX. Unused imports are not critical, but if you want to remove them, it is recommended to use the codemod script.
cd your_project
npx react-codemod update-react-imports
As a result:
- Remove any unused React imports
- All imports like import React from "react" will be changed to named import {useState} from "react". This is the preferred import method. Codemod will not affect imports like import * as React from "react", this is also a valid import and in version 17 it will work, but in the future we will ask you to get rid of it
The code:
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 something else in the react (for example a hook), then the named import will appear in the code:
Code
import React from 'react';
function App() {
const [text, setText] = React.useState('Hello World');
return <h1>{text}</h1>;
}
Replaced with the code:
import { useState } from 'react';
function App() {
const [text, setText] = useState('Hello World');
return <h1>{text}</h1>;
}
Removing unused imports will help prepare for the next versions of React (not 17) in which there will be support for ES modules and there will be no default export.
Acknowledgments
We thank the teams Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, and Flow for their help in integrating the new JSX transformation engine. We also thank the React community for their feedback and discussions on the RFC .