New JSX Transformation Engine in React 17 Release Candidate

React 17 Release Candidate introduces a new way to transform JSX. With it, in a bundle, you won't need React itself, although you still need it to use hooks. This is the main benefit of the new mechanism. Below is a short translation of an article on the ReactJS blog .



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:





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.



note
Gatsby 17.0.0-rc.2, npm update



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 .



All Articles