如何对 JSX 文件启用 ESLint 的 react-hooks 规则

解读

面试官想知道三件事:

  1. 你能否在 Grunt 体系 里把 ESLint 跑起来;
  2. 你能否让 ESLint 只针对 JSX 文件 生效,而不是全量扫描;
  3. 你能否把 react-hooks 规则集(react-hooks/rules-of-hooks、react-hooks/exhaustive-deps)注入到规则链里,并保证规则等级正确。

国内真实场景下,项目往往同时存在 JS/TS/JSX,构建机资源紧张,“只扫该扫的” 是 CI 考核指标之一;答不到“范围可控、规则可配、缓存可用”这三点,会被认为“仅会跑命令,不会工程化落地”。

知识点

  • grunt-eslint 插件的 files/src 匹配语法(支持 ! 反向、ext 通配)
  • ESLint 配置级联:.eslintrc.* vs grunt 任务内的 options.configFile
  • react-hooks 插件的注入方式:extends 数组 或 plugins + rules 手工声明
  • JSX 解析器:@babel/eslint-parser 与 ecmaFeatures.jsx 的取舍(国内项目普遍用 Babel,需同步设置 requireConfigFile:false)
  • 缓存与增量:grunt-eslint 的 cache 开关与 cacheLocation,降低 60%+ 扫描时间
  • 规则等级:'error' 会打断后续任务,'warn' 仅输出,CI 脚本需配合 force: true 防止 Grunt 退出码非 0

答案

  1. 安装依赖
    npm i -D grunt-eslint eslint-plugin-react-hooks @babel/core @babel/eslint-parser

  2. 在项目根新建 .eslintrc.js,仅声明 JSX 相关
    module.exports = {
    parser: '@babel/eslint-parser',
    parserOptions: {
    ecmaVersion: 2022,
    sourceType: 'module',
    ecmaFeatures: { jsx: true },
    requireConfigFile: false
    },
    plugins: ['react-hooks'],
    extends: [],
    rules: {
    'react-hooks/rules-of-hooks': 'error',
    'react-hooks/exhaustive-deps': 'warn'
    },
    overrides: [{
    files: ['**/*.jsx'],
    rules: {
    'react-hooks/exhaustive-deps': 'error' // JSX 文件里升级成 error
    }
    }]
    };

  3. Gruntfile.js 中注册任务
    module.exports = function(grunt) {
    grunt.initConfig({
    eslint: {
    jsx: {
    options: {
    configFile: '.eslintrc.js',
    cache: true,
    cacheLocation: 'node_modules/.cache/eslint-jsx/'
    },
    src: ['src/**/*.{jsx,tsx}'] // 只扫 JSX/TSX,其他文件阶段独立任务
    }
    }
    });

grunt.loadNpmTasks('grunt-eslint');
grunt.registerTask('lint:jsx', ['eslint:jsx']);
};

  1. 在 CI 脚本里
    npm run grunt lint:jsx
    若出现 error 级别规则违反,Grunt 会返回 exit 1,直接阻断流水线,符合国内“质量门禁”要求。

拓展思考

  • 如何把 TypeScript + JSX 一起管:把 parser 换成 @typescript-eslint/parser,并在 overrides 里对 tsx 文件关闭部分 react-hooks 规则,避免与 TS 类型检查冲突。
  • grunt-contrib-watch 联动:文件改动时只 lint 改动的 jsx,通过 grunt.event.on('watch',function(action, filepath) {}) 动态修改 src 数组,实现毫秒级增量检查
  • 产出 可视化报告:在 grunt-eslint 里加 options.format: 'html',并把输出文件托管到 nginx,让测试组无需命令行即可定位问题
  • 当项目升级到 ESLint 9 Flat Config 后,grunt-eslint 尚未官方支持,可先用 eslint.useFlatConfig 实验开关,或临时用 grunt-shell 调用 npx eslint,保证团队平滑过渡