ESLint 插件安装后为什么规则不生效?

书生シ奕玮 阅读 94

我装了个 eslint-plugin-react,也配了 extends,但自定义规则好像没起作用,是我哪里漏了吗?

我的 .eslintrc.js 配置里写了 "plugin:react/recommended",但像 react/no-unescaped-entities 这种规则还是不会报错。

module.exports = {
  extends: ['plugin:react/recommended'],
  plugins: ['react'],
  rules: {
    'react/no-unescaped-entities': 'error'
  }
};
我来解答 赞 17 收藏
二维码
手机扫码查看
2 条解答
轩辕亚会
我看了一下你的配置,有几个地方可以检查下。首先确认你的项目里确实安装了 eslint-plugin-react 这个包,跑个 npm list eslint-plugin-react 看看版本对不对。

然后这个配置看起来基本没问题,但建议把 extends 写完整路径试试:
module.exports = {
extends: ['eslint:recommended', 'plugin:react/recommended'],
plugins: ['react'],
rules: {
'react/no-unescaped-entities': 'error'
}
};


别忘了在文件开头加上注释指定要用的 parser,要不然规则可能识别不了:
// eslint-disable-next-line no-unused-vars
/* eslint-env es6 */

最后重启一下你的编辑器或者 ESLint server,有时候缓存的问题也挺烦人的。改一下就行,应该就能生效了。要是还不行就看看控制台报啥错误信息。
点赞
2026-03-30 19:01
Newb.璟春
根本原因是你的配置里把 pluginsextends 的顺序搞反了,而且没注意 extends 里已经隐式包含了插件注册,但如果你还手动写 plugins,就可能产生覆盖或冲突,特别是当某些规则依赖插件正确加载时,顺序和写法必须严格按 ESLint 的解析逻辑来。

ESLint 在解析配置时,是按以下顺序处理的:
1. 先加载 plugins 字段,注册插件(比如 eslint-plugin-react
2. 再处理 extends 字段,它会引入其他配置(比如 plugin:react/recommended
3. 最后合并 rules 字段,覆盖已有的规则配置

但问题在于,plugin:react/recommended 这个配置本身已经自动注册了 react 插件,你再在 plugins 里手动写一遍,虽然理论上 ESLint 不会报错,但某些版本(尤其是 ESLint v8+)对插件重复注册敏感,或者当你用 eslint-plugin-react 版本较老时(比如 v16 之前),它要求 plugins 必须显式声明,而 extends 里的 plugin:xxx/recommended 并不会自动加到 plugins 里——但反过来,如果你写了 plugins 却没写对位置,或者写在 extends 之后,就可能被覆盖或忽略。

更关键的是:很多 ESLint 插件的规则只有在插件被正确注册后,才能被识别和应用。比如 react/no-unescaped-entitieseslint-plugin-react 提供的自定义规则,如果插件没注册好,ESLint 根本不认识这个规则名,它会当作“未知规则”直接忽略,或者在 ESLint v9+ 里直接报错(取决于 unknownRules 的配置)。

我见过太多人卡在这里,以为是规则本身写错了,其实根本是插件没生效。验证方法很简单:在终端跑 npx eslint --print-config your-file.js,看输出里 rules 里有没有 react/no-unescaped-entities,如果压根没出现,说明插件根本没加载。

所以正确写法是:

module.exports = {
// 插件必须在 extends 之前声明,且只写一次
plugins: ['react'],
// extends 会引入预设规则集,其中 plugin:react/recommended 已经启用了 react 插件的推荐规则
// 注意:这里不需要再写 'plugin:react/recommended' 里的插件名,但 extends 本身不注册插件!
extends: [
'plugin:react/recommended'
],
rules: {
// 自定义规则,覆盖推荐配置里的默认设置(比如把 warn 改成 error)
'react/no-unescaped-entities': ['error', {
// 可选:指定允许哪些转义字符,比如允许 ' 但禁止   等
// 默认是 { allow: ['apos', 'quot', 'gt', 'lt', 'nbsp'] }
allow: ['apos', 'quot', 'gt', 'lt', 'nbsp', 'copy', 'reg', 'trade']
}]
}
};


但等等,还有个隐藏坑点:你用的 eslint-plugin-react 版本是不是太老了?
在 v16.x 及之前,plugin:react/recommended 并不会自动启用所有推荐规则(比如 react/no-unescaped-entities 是在 v16.0.0 才被加进 recommended 的),如果你用的是 v15 或更早版本,这个规则压根不在 recommended 里,自然不会生效。

你可以运行 npm ls eslint-plugin-react 看版本,如果低于 v16,建议升级:

npm i -D eslint-plugin-react@latest

升级后,再确认 plugin:react/recommended 里确实包含 react/no-unescaped-entities。你也可以自己去 node_modules/eslint-plugin-react/config/recommended.js 里翻一翻,看有没有这一行:

'react/no-unescaped-entities': ['error', { ... }]

如果没看到,说明你用的版本确实太老了。

另外,如果你用了 ESLint v9+,还要注意 override 配置会不会把 rules 给覆盖了。比如有些项目在 overrides 里写了 rules: {},但没加 react/no-unescaped-entities,那全局配置的 rules 就被局部覆盖掉了。

最后再给个最保险的写法,确保万无一失(尤其适合多团队协作项目):

module.exports = {
plugins: ['react'],
extends: [
// 先加载基础推荐配置(含 react 插件规则集)
'plugin:react/recommended',
// 如果你有其他扩展,比如 hooks、jsx-a11y,也放这里
// 注意顺序!后面的会覆盖前面的同名规则
],
rules: {
// 显式覆盖 react/no-unescaped-entities 的级别和参数
// 用数组写法能传额外参数,字符串 'error' 只能设级别
'react/no-unescaped-entities': ['error', {
// 自定义允许的字符,避免误报(比如 © 是允许的)
allow: ['apos', 'quot', 'gt', 'lt', 'nbsp', 'copy', 'reg', 'trade', 'euro', 'pound', 'yen']
}]
},
settings: {
// 建议加上这个,确保 react 插件能识别 JSX 语法
react: {
version: 'detect' // 自动检测项目中 react 版本
}
}
};


顺带说一句,react/no-unescaped-entities 这个规则默认只检查 JSX 中的未转义字符(比如  ),如果你在普通字符串里写 "hello & world",它不会报错——除非你配置了 jsx: false,但那样会失去 JSX 语义检查的意义。所以建议保留默认行为,只调整 allow 列表。

最后检查一遍:
- 插件装了没?npm ls eslint-plugin-react
- ESLint 能找到插件?node_modules 里有 eslint-plugin-react 目录
- 配置文件名对不对?.eslintrc.js.eslintrc.cjs.eslintrc.json 都能被识别,但别写成 .eslintrc.js.txt 这种低级错误(真有人这么干过)
- ESLint 版本够新?npx eslint --version 建议 v8.40+ 或 v9+

跑完 npx eslint src/your-file.jsx,看有没有报错。如果还是没动静,就用 --debug 参数看看插件加载日志:

npx eslint src/your-file.jsx --debug

一般日志里会出现类似 ESLint plugin: react loaded 的输出,如果没这行,说明插件根本没注册上,那就是路径或版本问题了。
点赞 4
2026-02-27 07:01