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 导入没有被删除,这样问题就解决了。

相关推荐
华仔啊3 小时前
别再写 TypeScript enum了!新枚举方式让 bundle 瞬间小20%
javascript·typescript
子兮曰8 小时前
🚀彻底掌握异步编程:async/await + Generator 深度解析与20个实战案例
前端·javascript·typescript
知否技术9 小时前
别再踩坑了!这份 Vue3+TypeScript 项目教程,赶紧收藏!
前端·typescript
嫣语岁月13 小时前
【BMS电池管理】基于BQ76920与STM32的BMS设计开发
c语言·vscode·stm32·单片机·嵌入式硬件
@AfeiyuO16 小时前
分类别柱状图(Vue3)
typescript·vue·echarts
一只小风华~16 小时前
Vue:条件渲染 (Conditional Rendering)
前端·javascript·vue.js·typescript·前端框架
大虾写代码18 小时前
vue3+TS项目配置Eslint+prettier+husky语法校验
前端·vue·eslint
996终结者21 小时前
同类软件对比(四):Jupyter vs PyCharm vs VS Code:Python开发工具终极选择指南
vscode·python·jupyter·pycharm·visual studio code
烛阴1 天前
【TS 设计模式完全指南】用适配器模式优雅地“兼容”一切
javascript·设计模式·typescript