什么情况会触发 'React' must be in scope when using JSX 呢
先看官方文档
💼🚫 This rule is enabled in the ☑️
recommendedconfig. This rule is disabled in the 🏃jsx-runtimeconfig.When using JSX,
<a />expands toReact.createElement("a"). Therefore theReactvariable must be in scope.
JSX(JavaScript XML)是一种 JS 的语法扩展,允许我们在JavaScript中编写HTML类似的代码,这也是React框架的根本特点之一。浏览器无法直接理解JSX,但像Create React App之类的脚手架则会通过babel等工具来实现JSX转换,将JSX代码转换为有效的JavaScript代码,让浏览器可以理解。
在React版本17.0之前,JSX在编译时由JSX转换器转换为 React.createElement() 函数调用。这需要我们在使用到JSX的文件中导入React。
让我们看看下面的功能组件作为一个例子:
function App() {
return <h1>Welcome to Eason!</h1>;
}
在编译时,它被转换为常规的JavaScript:
function App() {
return React.createElement('h1', null, 'Welcome to Eason!');
}
因此,如果我们没有在文件中引入过 React,则必然会因为 React 没有被定义而提示错误 'React' must be in scope when using JSX。
解决方案
版本低于 React v17.0
所以对于 React 版本低于17的项目而言,如果出现 'React' must be in scope when using JSX 的报错,只需要在文件中显式引入 React即可。在编译后,js 代码将会呈现成如下形式:
import React from 'react';
function App() {
return React.createElement('h1', null, 'Welcome to Eason!');
}
版本高于 React v17.0
随着 React v17.0 中新的JSX转换方式引入,React 官方与 babel 进行了合作,可以直接通过新的插件对 jsx 语法进行转换,不需要依赖 React.createElement。因此如果在React17版本后只使用 jsx 语法,并且不使用其他的 React 提供的 api 时,可以不引入 React,应用程序依然能够正常运行。
官方文档对于 React v17.0 转换 jsx 的说明:
However, this is not perfect:
- Because JSX was compiled into
React.createElement,Reactneeded to be in scope if you used JSX.- There are some performance improvements and simplifications that
React.createElementdoes not allow.To solve these issues, React 17 introduces two new entry points to the React package that are intended to only be used by compilers like Babel and TypeScript. Instead of transforming JSX to
React.createElement, the new JSX transform automatically imports special functions from those new entry points in the React package and calls them.
为了解决这些使用 JSX 需要在文件中引入 React 以及 React.createElement 本身的一些性能问题,React 17 引入了 React 包的两个新入口点,这些入口点仅供像 Babel 和 TypeScript 这样的编译器使用。新的 JSX 转换器不再将 JSX 转换为 React.createElement,而是自动从 React 包中的这些新入口点导入特殊函数并调用它们。
添加 'plugin:react/jsx-runtime' 插件
也就是如ESLint官方文档中所说,当我们使用 React v17.0 及之后的 React 版本时,我们需要将 'React' must be in scope when using JSX 这条判断规则禁用掉,即在我们的 eslint 配置文件中添加 plugin:
'plugin:react/jsx-runtime'
extends:
- 'plugin:@typescript-eslint/recommended'
- 'plugin:react/recommended'
- 'plugin:react-hooks/recommended'
- 'eslint:recommended'
- 'plugin:react/jsx-runtime'
当新插件被引入后,我们的 JSX 代码在编译后会呈现如下:
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Welcome to Eason!' });
}
也就是说,对于版本高于 React v17.0 的项目,不再需要在组件中导入React,就可以使用 JSX。如果我们在确认了 React 版本之后仍然收到 'React' must be in scope when using JSX,那就还需要更新ESLint配置。
安全禁用 'React' must be in scope when using JSX
确定React版本为 v17.0 或更高版本时,就可以安全地禁用'React' must be in scope when using JSX。有两种主要方法可以更新ESLint配置。如果项目中存在 .eslintrc.js 或 .eslintrc.json 的文件,可以将以下规则添加到 eslint 配置文件中:
"rules": {
// ...
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "off",
}
同时,也可以在项目的 package.json 文件中添加配置:
{
"name": "new-project",
// ...
"dependencies": {
// ...
},
"eslintConfig": {
"extends": [
"react-app"
],
"rules": {
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
},
}
其他方案
升级 React-Scripts
对于 Create-React-App 脚手架搭建的项目,可以尝试升级 React-Scripts
// npm
npm install react-scripts@latest
// yarn
yarn add react-scripts@latest
删除 node_modules 及 package-lock.json 文件并重新安装
# 删除 node_modules 及 package-lock.json
rm -rf node_modules
rm -f package-lock.json
rm -f yarn.lock
# 清除 npm 的缓存
npm cache clean --force
npm install
npm install react-scripts@latest
更新 React 和 react-dom 的版本
# 使用 npm
npm install react@latest react-dom@latest
# 使用 ts 的项目
npm install --save-dev @types/react@latest @types/react-dom@latest
# ------------------------------
# 使用 yarn
yarn add react@latest react-dom@latest
# 使用 ts 的项目
yarn add @types/react@latest @types/react-dom@latest --dev
总结
'React' must be in scope when using JSX 的报错主要发生在 React v17.0 之前的早期版本中,当在文件中使用到 JSX 语法且没有正确引入 React 时。同时,在高于 React v17 的更高版本中,当 ESLint 配置错误时,或者当 node_modules 文件夹中的一些依赖项被错误地安装时,也会报这个错误。