什么是JSX转换
由于浏览器无法立即理解JSX,因此开发人员依靠Babel或Typescript等编译器将JSX转换为纯JS。React 17 Release Candidate引入了一个新的,可选的JSX到JS转换机制。
好处如下:
- 在不使用React Import的情况下使用JSX
- 根据设置的不同,捆绑包可能会略有减少
- 将来,将提供功能以简化工作并做出反应
(也许我没有完全准确地翻译它-这是原始内容:它将使将来的改进减少您学习React所需的概念的数量。)
升级不会以任何方式更改JSX本身,并且所有编译器都可以正常工作。没有放弃它们的计划。计划为较早版本的React支持新的JSX转换机制:16.x,15.x,14.x,此处是升级说明。
发生了什么变化
旧的JSX转换的工作方式如下:
代码
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
转化成
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
但这不是很好,这是为什么:
- 由于JSX编译为React.createElement,因此React需要在范围内
- 有几个选项可以提高速度并简化React.createElement块
为了解决这个问题,React 17引入了两个新的入口点,供其他工具(例如Babel和Typescript)使用,现在不再转换为React.createElement,而是从React包中导入并调用新函数。
假设您的代码如下所示:
function App() {
return <h1>Hello World</h1>;
}
经过新的转换后,它将如下所示:
// 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' });
}
新机制不会导入React,尽管钩子仍需要工作。
新的转换与所有现有的JSX代码完全兼容,您无需进行任何更改。这是有关新JSX转换如何工作的技术细节。
如何升级
如果您还没有准备好升级或正在将JSX用于其他库,请不要担心,不会删除旧的转换并将其受支持。
要升级,您需要做两件事:
- 具有新转换支持的React版本。到目前为止只有17个,但在将来的16.x,15.x和14.x
- 兼容的编译器(见下文)
Create React App
创建React App支持将在v4.0版本中进行,现在处于beta测试中(截至09/22/2020)
。Next.js
Next.js v9.5.3 +已将新的React转换用于兼容版本。
Gatsby
Gatsby v2.24.5 +已将新的React转换用于兼容版本。
v7.9.0及更高版本的手动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
如果您使用巴别塔/预设反应:
#npm
npm update @babel/core @babel/preset-react
#yarn
yarn upgrade @babel/core @babel/preset-react
现在用于将JSX转换为巴别塔/ plugin-transform-react-jsx和 巴别塔/ preset-react,默认值为{“ runtime”:“ classic”},这是转换的旧版本。要启用新的转换,需要使用{“ runtime”:“ automatic”}选项(
如果使用)巴别塔/预设反应:
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
如果您正在使用 巴别塔/ plugin-transform-react-jsx:
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
从Babel 8开始,两个插件的默认设置均为“自动”。@ babel / plugin-transform-react-jsx和@ babel / preset-react这里有更多详细的文档。
注意
, importSource , . , .
ESLint
如果您具有eslint-plugin-react插件,则不再需要react / jsx-uses-react和react / react-in-jsx-scope规则,可以将其删除。
{
// ...
"rules": {
// ...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
从4.1 beta版开始,TypeScript支持JSX转换。
流程
支持从版本JSX转换0.126.0和更高。
如何去除未使用的React导入
由于新的JSX转换将自动导入react / jsx-runtime,因此使用JSX不再需要React。未使用的导入并不重要,但是如果要删除它们,建议使用codemod脚本。
cd your_project
npx react-codemod update-react-imports
结果是:
- 删除任何未使用的React导入
- 所有导入(例如从“ react”导入import React)都将从“ react”更改为命名导入{useState}。这是首选的导入方法。Codemod不会影响像import *这样的导入,例如来自“ react”的React,这也是有效的导入,在版本17中它可以工作,但是将来我们会要求您摆脱它
代码:
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
将被替换为:
function App() {
return <h1>Hello World</h1>;
}
如果你用别的东西的反应(例如钩),然后命名的进口将出现在代码:
代码
import React from 'react';
function App() {
const [text, setText] = React.useState('Hello World');
return <h1>{text}</h1>;
}
替换为代码:
import { useState } from 'react';
function App() {
const [text, setText] = useState('Hello World');
return <h1>{text}</h1>;
}
删除未使用的导入将有助于为React的下一版本(不是17)做准备,在该版本中将支持ES模块并且没有默认导出。
致谢
我们要感谢Babel,TypeScript,Create React App,Next.js,Gatsby,ESLint和Flow团队在集成新JSX转换引擎方面的帮助。我们也感谢React社区对RFC的反馈和讨论。