React useRef为何能跳过依赖警告?自定义Hook如何实现相同效果?
问题解答
1. 为什么原生useRef不会触发依赖警告?
react-hooks/exhaustive-deps 是eslint-plugin-react-hooks插件的内置规则,React官方脚手架默认集成开启。这个规则内部预先硬编码了所有React原生Hook的返回值特性:比如它明确知道useRef的返回值引用永远不会变化、useState返回的setter、useReducer返回的dispatch也都是全局稳定的,所以这些值即便在useEffect等钩子中用到,也不会被判定为缺失依赖。
这个特殊判定完全是ESLint静态检查层面的逻辑,和React运行时没有关系,也不存在JS语法层面的魔法。
2. 自定义Hook为什么会触发警告?
因为ESLint规则默认不识别任何自定义Hook的返回值特性,只要是在副作用回调中用到的外层作用域变量,规则都会默认要求加入依赖数组,所以你封装的useCustomRef就算逻辑上和原生useRef完全一致,也会触发警告。
3. 自定义Hook如何实现和原生Hook一致的豁免效果?
有两种常用解决方案:
方案1:全局配置ESLint规则(推荐)
从eslint-plugin-react-hooks v4.1.0版本开始,规则支持配置自定义稳定Hook列表,你只需要在项目的ESLint配置文件(.eslintrc、.eslintrc.json等)中添加如下配置:
{ "rules": { "react-hooks/exhaustive-deps": [ "warn", { "stableHooks": { // 键为你的自定义Hook名称,值设为true即代表该Hook返回值永远稳定 "useCustomRef": true, // 其他返回稳定值的自定义Hook都可以在这里添加 "useCustomDispatch": true } } ] } }
配置完成后重启ESLint服务,这些自定义Hook的返回值就会和原生useRef一样,不会被要求加入依赖数组。
方案2:局部禁用规则(临时解决方案)
如果只是个别场景遇到该问题,不想修改全局配置,可以在依赖数组上方加注释临时禁用该行规则:
useEffect(() => { ref2.current.otherRef = ref1.current; // eslint-disable-next-line react-hooks/exhaustive-deps }, []);
注意该方案容易掩盖真实的依赖缺失问题,不建议大量使用。
内容的提问来源于stack exchange,提问作者Yanick Rochon
相关产品推荐
相关产品推荐

