How to enable new JSX transform in React?
Wojciech Maj
Posted on August 11, 2020
The biggest feature of React 17, as React team claims, is that there are no new features. This isn't however entirely true.
In Babel 7.9.0, a new JSX transform was announced. It could only be used in experimental React releases. Until now!
Before we dive into how to enable this feature, let's see the advantages:
No more import React from 'react'
Yes! You'll no longer need to import React to each. and. every. component. you write. Instead, it will be imported automatically!
Well, not quite. If you use hooks, lazy
, Suspense
or any other import, you will still need to import them all manually. But no more importing React
if you're not using React
explicitly in your code, e.g. by calling React.useState
.
Smaller bundle
A side effect of this change is also a slightly smaller bundle. In my case, on a moderately sized commercial application with ~1500 components, the savings were around 10.5 KiB. It ain't much, but arguably a welcome improvement.
Where do the savings come from? Take a look at transpiled code, before & after the change we're about to make:
import React from "react";
function Foo() {
return React.createElement("div");
}
import { jsx as _jsx } from "react/jsx-runtime";
function Foo() {
return _jsx("div");
}
Turns out, this can add up!
Enough talking, let's do it!
Make sure you're all up to date
To continue, you're going to need:
- Babel &
@babel/preset-react
7.9.0
or later - React:
- 17:
17.0.0
or later, - 16:
16.14.0
or later, - 15:
15.7.0
or later, - 0.14:
0.14.10
or later
- 17:
For example, you can use
npm install @babel/core@^7.9.0 @babel/preset-react@^7.9.0 --dev
npm install react@^16.14.0 react-dom@^16.14.0
or
yarn add @babel/core@^7.9.0 @babel/preset-react@^7.9.0 --dev
yarn add react@^16.14.0 react-dom@^16.14.0
to update your React 16 app.
You can also jump straight to React 17. Note that React 17 contains some breaking changes when compared to React 16. Upgrade carefully!
Babel configuration
Your Babel configuration (.babelrc
, .babelrc.json
, or similar) needs a small change: In presets
section, to
"@babel/preset-react"
preset you'll now need to pass "runtime": "automatic"
option. Change the above line to:
["@babel/preset-react", {
"runtime": "automatic"
}]
That's it! You're done! 🥳
Cleaning up
Alright, not quite. You're now left with redundant React imports. Cleaning them up is optional, because modern bundlers will ignore unused imports. If you still want to do the cleaning, continue reading.
If you used e.g. React.useState
or <React.Fragment>
(as opposed to useState
or <>
), the easiest approach would be to get rid of all React.*
occurrences first.
Then, you'll be free to remove "pure" React imports by replacing (using RegEx):
import React from ['"]react['"];?\n
with an empty string, and replacing
import React,\s?(\{.*\})\s?from (['"]react['"])
with
import $1 from $2
which should leave only named imports in a vast majority of cases.
ESLint configuration
Changes are ESLint will complain about you no longer importing React
in files where you're using JSX. If that's the case, all you need to do is simply turn off these rules:
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off",
Happy coding!
Posted on August 11, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.