My Journey
Every major release of any dependency leads to thoughts of âOh man, I hope this major upgrade isnât too painfulâ. When I saw that React had been released on npm outdated, my reaction was no different. But after looking at their React 17 release blog post, I breathed a sign of relief â there were no breaking changes or new features. But, it did mention an interesting optional change: the new JSX Transform.
JSX Transform
JSX transform is needed so your source code can be converted into code the browser understands. This is where compilers such as Babel or TypeScript come in â they convert your developer-friendly code into browser-friendly code. The old JSX Transform required you to import React since this would tell your compiler that this file would require some React JSX magic. Otherwise, the compilation will fail. This is why the ESLint plugin eslint-plugin-react includes and recommends the react/react-in-jsx-scope and react/jsx-uses-react rules.
The new JSX transform, however, no longer requires the React import. The compilation will still work without a single change to your JSX code! Internally, the transform magic works differently, but the end result is the same â your code works exactly as before in the browser.
React Utils
While you no longer need to import React, you still may have to import the React utils, hooks, and other tools if you use them. These should be imported via their named imports.
import { Component, lazy, Suspense, useState } from 'react';
ESLint
This new transform will conflict with some ESLint rules. If you are using react/react-in-jsx-scope or react/jsx-uses-react, either explicitly or through a common configuration (such as Airbnbâs ESLint configuration or eslint-plugin-reactâs recommended), they need to be disabled.
// .eslintrc.js
module.exports = {
rules: {
'react/react-in-jsx-scope': 'off',
'react/jsx-uses-react': 'off'
}
}
Configuration
This feature does require a small bit of configuration though. If youâre using Create React Appâs react-scripts, youâll have to unfortunately bite the bullet and upgrade to 4.0.
If you are manually setting up Babel, support for this transform requires at least Babel 7.9 and either @babel/preset-react or @babel/plugin-transform-react-jsx using automatic runtime in your babel configuration file.
// for @babel/preset-react
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
// for @babel/plugin-transform-react-jsx
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
Codemod
To support this migration, the React team has thankfully graced us with a codemod:
npx react-codemod update-react-imports
After a few questions about your environment, this script should automatically remove default React imports and add in named imports if you use any React utils. Of course, verify the changes as this codemod may not be perfect.
Note: I personally encountered a MODULENOT_FOUND (_Error: Cannot find module â@babel/runtime-corejs3/helpers/interopRequireDefaultâ) issue that I still have not found the root cause for. But I did find a workaround by temporarily deleting (or commenting out) the babel configuration file.
Supported Versions
Besides React 17, the React team has also backported this feature to React 16.14, React 15.7, and React 0.14.10 so you can take advantage of this feature without dealing with a major upgrade. But if youâre on React 16, the upgrade to React 17 is painless.
Final Thoughts
Is there any benefit to this? Not really. But do I like this change? Yes absolutely. It always felt silly to me that I would import something that wasnât (explicitly) used as if it was an unused import or variable. Since the new JSX transform requires minimal configuration changes and has a codemod to automatically refactor everything, you may as well just start using it.