为何React导入不删,它可是之魂?

摘要:问题 使用 Delete unused imports 操作时,同时删掉了 import React from 'react';。 为什么不能删掉呢?因为代码 push 到远程仓库后会走 CI
问题 使用 Delete unused imports 操作时,同时删掉了 import React from 'react';。 为什么不能删掉呢?因为代码 push 到远程仓库后会走 CI 流程, CI 流程里有代码检查节点进行 ESLint 检查 CI 节点的 ESLint 规则开发者无法修改或者覆盖。其中有一条规则是 { "react/react-in-jsx-scope": "error" } 它表示当 ESLint 检测到 JSX 代码但 React 没有被正确引入时,会报错。在 React 17+ 版本中,引入了新的 JSX 转换方式,可以不需要显式引入 React。为什么这条规则仍然存在,因为有大量使用低版本 React 的仓库需要兼容。 接下来我们要做的是: 保持 tsx 文件中存在 import React from 'react'; 保持 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 错误时,本地开发使用的编辑器才能给出错误或警告。由于规则集中包含了 { "react/react-in-jsx-scope": "error" } 所以此处就不会有 ESLint 错误抛出了。 为什么 React 17- 必须 React Must Be in Scope 由于 JSX 编译为对 React.createElement 的调用,因此 React 库也必须始终在 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: 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 { "extends": "./src/.umi/tsconfig.json" } 使用了 "extends"属性来继承另一个配置文件,这是 umi 框架内置的 tsconfig,目前很多元框架都是这么做的。我们可以点跳转过去,看看这个配置文件内容,只看相关的部分 { "compilerOptions": { "jsx": "react-jsx", } } jsx 属性控制JSX结构在JavaScript文件中的输出方式。
阅读全文