React Doctor:一键扫描代码库,输出健康评分与诊断建议,多方式助力代码优化!
2026/5/12 22:53:40 网站建设 项目流程

解决代码质量问题

你的代码编写工具编写的 React 代码质量欠佳,而 React Doctor 能解决这个问题。只需一个命令,它就能扫描你的代码库,并输出 0 到 100 的健康评分,同时给出可操作的诊断建议。它支持 Next.js、Vite 和 React Native。

立即体验

在项目根目录运行以下命令进行安装:`npx -y react-doctor@latest`。你会得到一个评分(75 分及以上为优秀,50 到 74 分需要改进,50 分以下为危急),以及一份涵盖状态与副作用、性能、架构、安全、可访问性和死代码等方面的问题列表。规则会根据你的框架和 React 版本自动切换。

为代码编写工具安装

教导你的代码编写工具遵循 React 最佳实践,从源头上避免编写糟糕的代码。运行 `npx -y react-doctor@latest install`,系统会提示你选择要安装的检测工具。使用 `--yes` 参数可跳过提示。它支持 Claude Code、Cursor、Codex、OpenCode 等 50 多种工具。

GitHub Actions

本仓库提供了一个复合操作。将其放入 `.github/workflows/react-doctor.yml` 文件中:

name: React Doctor on: pull_request: push: branches: [main] permissions: contents: read pull-requests: write # 发布 PR 评论所需 jobs: react-doctor: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 with: fetch-depth: 0 # `diff` 所需 - uses: millionco/react-doctor@main with: diff: main github-token: ${{ secrets.GITHUB_TOKEN }}
当在 `pull_request` 事件中设置了 `github-token` 时,检测结果会作为 PR 评论发布(并更新)。该操作还会输出一个评分(0 - 100),你可以在后续步骤中使用。输入参数包括:`directory`、`verbose`、`project`、`diff`、`github-token`、`fail-on`(error / warning / none)、`offline`、`node-version`。完整描述请参考 `action.yml`。

如果你不想添加市场操作,直接使用 `npx` 命令也可以:

- run: npx -y react-doctor@latest --fail-on warning

配置

在项目根目录创建 `react-doctor.config.json` 文件:

{ "ignore": { "rules": ["react/no-danger", "jsx-a11y/no-autofocus"], "files": ["src/generated/**"], "overrides": [ { "files": ["components/modules/diff/**"], "rules": ["react-doctor/no-array-index-as-key", "react-doctor/no-render-in-render"] }, { "files": ["components/search/HighlightedSnippet.tsx"], "rules": ["react/no-danger"] } ] } }
这里有三层嵌套的键,对应三种不同的粒度级别,你可以选择最合适的一种:`ignore.rules` 可在整个代码库中禁用某个规则;`ignore.files` 可对匹配的文件禁用所有规则(谨慎使用,因为会降低无关规则的覆盖率);`ignore.overrides` 仅对匹配的文件禁用列出的规则,其他规则仍会生效。当某个文件(或通配符匹配的文件)确实需要豁免一两条规则,但仍需对其他规则进行扫描时,这是你需要的配置方式。你也可以在 `package.json` 中使用 "reactDoctor" 键。CLI 标志始终会覆盖配置文件中的值。

React Doctor 会遵循 `.gitignore`、`.eslintignore`、`.oxlintignore`、`.prettierignore` 以及 `.gitattributes` 中的 `linguist-vendored` / `linguist-generated` 注释。内联的 `// eslint-disable*` 和 `// oxlint-disable*` 注释也会被识别。如果你有 JSON 格式的 `oxlint` 或 `eslint` 配置文件(`.oxlintrc.json` 或 `.eslintrc.json`),其规则会自动合并到扫描中,并计入评分。设置 `adoptExistingLintConfig: false` 可选择不合并。

可选的配套插件

当以下 ESLint 插件安装在被扫描的项目中(或在你的单仓库中提升)时,React Doctor 会将它们的规则纳入同一扫描。这两个插件都被列为可选的对等依赖项,你可以按需安装。

  • `eslint-plugin-react-hooks`(v6 或 v7):当项目中检测到 React Compiler 时,会触发 React Compiler 前端的正确性规则。命名空间为 `react-hooks-js/*`。
  • `eslint-plugin-react-you-might-not-need-an-effect`(v0.10+):与 React Doctor 原生的状态与副作用规则一起运行的补充规则,将副作用视为反模式(如 `no-derived-state`、`no-chain-state-updates`、`no-event-handler`、`no-pass-data-to-parent` 等)。命名空间为 `effect/*`。

内联抑制

// react-doctor-disable-next-line react-doctor/no-cascading-set-state useEffect(() => { setA(value); setB(value); }, [value]);
当同一行触发两条规则时,有两种等效的处理方式。一种是在单个注释中用逗号分隔规则 ID:
// react-doctor-disable-next-line react-doctor/rerender-state-only-in-handlers, react-doctor/no-derived-useState const [localSearch, setLocalSearch] = useState(searchQuery);
另一种是在诊断信息上方为每条规则堆叠一个注释。只要注释和目标行之间没有其他内容(除了其他 `react-doctor-disable-next-line` 注释),堆叠的注释就会生效:
// react-doctor-disable-next-line react-doctor/rerender-state-only-in-handlers // react-doctor-disable-next-line react-doctor/no-derived-useState const [localSearch, setLocalSearch] = useState(searchQuery);
堆叠注释之间有代码行会中断规则链,只有诊断信息正上方的注释(以及堆叠在其上的连续 `react-doctor-disable-next-line` 注释)会生效。如果注释看起来相邻但规则仍然触发,运行 `react-doctor --explain`,它会报告是否找到附近的抑制注释、覆盖的规则以及未应用的原因。块注释在 JSX 中也有效:
{/* react-doctor-disable-next-line react/no-danger */}
对于多行 JSX,将注释直接放在开始标签上方可覆盖整个属性列表(符合 ESLint 约定)。

独立的 lint 插件

相同的规则集同时作为 `oxlint` 插件和 ESLint 插件提供,你可以将其集成到项目现有的 lint 引擎中。

`oxlint` 在 `.oxlintrc.json` 中的配置:

{ "jsPlugins": [ { "name": "react-doctor", "specifier": "react-doctor/oxlint-plugin" } ], "rules": { "react-doctor/no-fetch-in-effect": "warn", "react-doctor/no-derived-state-effect": "warn" } }

ESLint 扁平配置:

import reactDoctor from "react-doctor/eslint-plugin"; export default [ reactDoctor.configs.recommended, reactDoctor.configs.next, reactDoctor.configs["react-native"], reactDoctor.configs["tanstack-start"], reactDoctor.configs["tanstack-query"] ];
完整的规则列表位于 `oxlint-config.ts` 文件中。

CLI 参考

用法:`react-doctor [directory] [options]`

选项:

  • `-v, --version`:显示版本号
  • `--no-lint`:跳过 lint 检查
  • `--no-dead-code`:跳过死代码检测
  • `--verbose`:显示每个规则和每个文件的详细信息(默认显示前 3 条规则)
  • `--score`:仅输出评分
  • `--json`:输出单个结构化的 JSON 报告
  • `-y, --yes`:跳过提示,扫描所有工作区项目
  • `--full`:跳过提示,始终进行全面扫描
  • `--project `:选择工作区项目(多个项目用逗号分隔)
  • `--diff [base]`:仅扫描与基础分支相比有更改的文件
  • `--staged`:仅扫描暂存文件(用于预提交钩子)
  • `--offline`:跳过遥测
  • `--fail-on `:根据诊断结果以错误状态退出:error、warning、none
  • `--annotations`:将诊断结果输出为 GitHub Actions 注释
  • `--explain `:诊断规则触发的原因或抑制注释未生效的原因
  • `--why `:`--explain` 的别名
  • `-h, --help`:显示帮助信息

当抑制注释不起作用时,`--explain`(或其别名 `--why`)会报告扫描器在该位置的检测情况,包括附近的 `react-doctor-disable-next-line` 注释未应用的原因。诊断会区分常见的失败模式,如相邻注释针对的是不同规则(使用逗号分隔形式)、注释和诊断信息之间有代码行(规则链中断)或根本没有附近的抑制注释。使用 `--verbose` 时,每个标记位置都会内联显示相同的提示信息,`--json` 输出中会包含 `diagnostic.suppressionHint`,因此一次扫描可以同时作为抑制注释的审核,无需额外的标志。`--json` 会在标准输出上生成一个可解析的对象,同时抑制所有人类可读的输出。错误仍然会生成一个 `ok: false` 的 JSON 对象,因此标准输出始终是一个有效的文档。

配置键

类型默认值说明
`ignore.rules``string[]``[]`要忽略的规则列表
`ignore.files``string[]``[]`要忽略的文件列表
`ignore.overrides``{ files, rules? }[]``[]`覆盖规则的配置
`lint``boolean``true`是否进行 lint 检查
`deadCode``boolean``true`是否进行死代码检测
`verbose``boolean``false`是否显示详细信息
`diff``boolean | string`仅扫描有更改的文件
`failOn``"error" | "warning" | "none"``"none"`达到何种级别时以错误状态退出
`customRulesOnly``boolean``false`是否仅使用自定义规则
`share``boolean``true`是否共享数据
`textComponents``string[]``[]`处理 `rn-no-raw-text` 规则时,将这些组件视为文本容器
`rawTextWrapperComponents``string[]``[]`处理 `rn-no-raw-text` 规则时,这些组件可安全包裹纯文本子元素
`respectInlineDisables``boolean``true`是否尊重内联禁用注释
`adoptExistingLintConfig``boolean``true`是否采用现有的 lint 配置

`textComponents` 是 `rn-no-raw-text` 规则的通用豁免选项,列出那些行为类似于 React Native 的 `` 组件(如自定义的 Typography、NativeTabs.Trigger.Label 等),规则会将它们视为文本容器,而不考虑其子元素的外观。`rawTextWrapperComponents` 是更精细的选项,适用于那些本身不是文本元素,但能安全地将纯字符串子元素传递到内部的组件(如 heroui-native 的 Button,它会将子元素字符串化并通过 ButtonLabel 渲染)。只有当这些包装组件的子元素完全可字符串化时,才会抑制 `rn-no-raw-text` 规则。如果包装组件包含混合子元素(如 ``),仍然会报告问题,因为该包装组件无法安全地将原始文本与兄弟 JSX 元素一起传递。

Node.js API

import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api"; const result = await diagnose("./path/to/your/react-project"); console.log(result.score); // { score: 82, label: "Great" } 或 null console.log(result.diagnostics); // Diagnostic[] console.log(result.project); // 检测到的框架、React 版本等 diagnose 接受第二个参数:{ lint?: boolean, deadCode?: boolean }。 const report = toJsonReport(result, { version: "1.0.0" }); const counts = summarizeDiagnostics(result.diagnostics); react-doctor/api 重新导出了 JsonReport、JsonReportSummary、JsonReportProjectEntry、JsonReportMode,以及底层的 buildJsonReport 和 buildJsonReportError 构建器。完整的类型定义请参考 `packages/react-doctor/src/api.ts`。

排行榜

由 React Doctor 扫描的顶级 React 代码库,按评分排名。数据自动从 `millionco/react-doctor-benchmarks` 更新。

仓库评分
executor94
nodejs.org86
tldraw70
t3code68
better-auth64
excalidraw63
mastra63
payload60
typebot57
plane56

查看完整排行榜。

资源与贡献

  • 想试用?查看演示。
  • 想贡献代码?克隆仓库,安装依赖,构建项目,然后提交 PR。
    git clone https://github.com/millionco/react-doctor cd react-doctor pnpm install pnpm build node packages/react-doctor/bin/react-doctor.js /path/to/your/react-project
  • 发现 bug?前往问题跟踪器。

许可证

React Doctor 是 MIT 许可的开源软件。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询