VS Code 操作 “Delete unused imports” 时,不删除 React 导入

问题

使用 Delete unused imports 操作时,同时删掉了 import React from 'react';

为什么不能删掉呢?因为代码 push 到远程仓库后会走 CI 流程, CI 流程里有代码检查节点进行 ESLint 检查

CI 节点的 ESLint 规则开发者无法修改或者覆盖。其中有一条规则是

json 复制代码
{
    "react/react-in-jsx-scope": "error"
}

它表示当 ESLint 检测到 JSX 代码但 React 没有被正确引入时,会报错。在 React 17+ 版本中,引入了新的 JSX 转换方式,可以不需要显式引入 React。为什么这条规则仍然存在,因为有大量使用低版本 React 的仓库需要兼容。

接下来我们要做的是:

  1. 保持 tsx 文件中存在 import React from 'react';
  2. 保持 delete unused imports 时,它不会被删掉

寻找原因

把鼠标放到 Button 上,显示了 2 条被检测出来的错误,一条 ESLint 检测出的,另一条是 TypeScript 的。

把鼠标放到 React 上,只显示了 1 条被检测出来的错误,是 TypeScript 的。

这表明使用 Delete unused imports 操作时,是 TypeScript 进行了删除操作, TypeScript 认为 React 是不必导入的, React 被 TypeScript 识别为未使用的变量。现在我们了解到我们要从 typescript 层面解决这个问题,可能跟 tsconfig 有关。

为什么这里没有抛出 ESLint 错误呢?因为此仓库的 ESLint 配置与 CI 代码检查节点的 ESLint 规则是相同的, 这样在出现 ESLint 错误时,本地开发使用的编辑器才能给出错误或警告。由于规则集中包含了

json 复制代码
{
    "react/react-in-jsx-scope": "error"
}

所以此处就不会有 ESLint 错误抛出了。

为什么 React 17- 必须 React Must Be in Scope

由于 JSX 编译为对 React.createElement 的调用,因此 React 库也必须始终在 JSX 代码的范围内。例如:

jsx 复制代码
const element = <div>Hello</div>;

// React 17 及之前编译为
const element = React.createElement("div", null, "Hello");

关键点​是编译后的代码直接调用了 React.createElement(),因此 React必须是一个已定义的变量。

React 17 引入了新的 JSX 转换(New JSX Transform),不再需要手动导入 React:

jsx 复制代码
function Component() {
  return <div>Hello</div>; // React 17+ 配合新 JSX 转换, 编译为 _jsxRuntime.jsx(...),无需 React
}

新转换会从 react/jsx-runtime 自动导入 jsx 或 jsxs 函数,不再依赖 React.createElement。简单说就是新 JSX 转换可省略导入,但需配置工具链支持,相关工具在编译阶段帮我们做了。

解决

上面我们了解到使用 VS Code 的 Delete unused imports 操作时,是 TypeScript 进行了删除操作,我们要让 TypeScript 识别到 React 导入不是一个未被使用的变量。我们还了解了为什么 React 17 之前必须 React Must Be in Scope。

接下来我们看看仓库的 tsconfig

json 复制代码
{
  "extends": "./src/.umi/tsconfig.json"
}

使用了 "extends"属性来继承另一个配置文件,这是 umi 框架内置的 tsconfig,目前很多元框架都是这么做的。我们可以点跳转过去,看看这个配置文件内容,只看相关的部分

json 复制代码
{
  "compilerOptions": {
    "jsx": "react-jsx",
  }
}

jsx 属性控制JSX结构在JavaScript文件中的输出方式。它还有以下值:

  • react-jsx:生成.js文件时将JSX转换为针对生产环境优化的_jsx调用
  • react-jsxdev:生成.js文件时将JSX转换为仅用于开发的_jsx调用
  • preserve:生成.jsx文件且保持JSX原样不变
  • react-native:生成.js文件且保持JSX原样不变
  • react:生成.js文件时将JSX转换为等效的 React.createElement 调用

框架内置的 jsx 被配置为 "react-jsx",这是正常的,因为当前版本的框架使用的 React 版本为 18,显然,它不需要在 tsx 或 jsx 文件顶部导入 React 了。

所以,我们就找到答案了,只要将 jsx 属性的值改为 react 就可以解决这个问题。但是我们不能修改框架内置的配置文件,怎么办呢?可以重新声明此选项以覆盖框架内置 tsconfig。

json 复制代码
{
  "extends": "./src/.umi/tsconfig.json",
  "compilerOptions": {
    "jsx": "react"
  }
}

验证

修改配置后,我们来重启下 VS Code TS Server。

quick fix 菜单已经没有 Delete unused imports 选项了,只有一个未使用变量 Button 被检测到。

我们把鼠标放到 React 上查看是否还有未使用的 ts 错误抛出:

错误消失了。我们再导入一个变量验证 Delete unused imports 是否会删除 React 的导入。

只删除了未使用的变量, React 导入没有被删除,这样问题就解决了。

相关推荐
昨晚我输给了一辆AE867 小时前
为什么现在不推荐使用 React.FC 了?
前端·react.js·typescript
Wect13 小时前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
Dilettante25813 小时前
这一招让 Node 后端服务启动速度提升 75%!
typescript·node.js
jonjia1 天前
模块、脚本与声明文件
typescript
jonjia1 天前
配置 TypeScript
typescript
jonjia1 天前
TypeScript 工具函数开发
typescript
jonjia1 天前
注解与断言
typescript
jonjia1 天前
IDE 超能力
typescript
jonjia1 天前
对象类型
typescript
jonjia1 天前
快速搭建 TypeScript 开发环境
typescript