如何标记自定义Hook的返回值为已记忆状态?
解决自定义Hook的ESLint依赖警告问题
第一步:修复useToggle的基础bug
你的useToggle存在逻辑错误:当前代码中const toggle = setVal(prevVal => !prevVal);会直接调用setVal,导致组件挂载时就触发状态切换。正确写法是将toggole定义为箭头函数,仅在调用时执行状态更新:
import { useState, VoidFn } from 'react'; function useToggle(initialValue: boolean): [boolean, VoidFn] { const [val, setVal] = useState<boolean>(initialValue); // 修正为箭头函数,避免挂载时直接执行 const toggle = () => setVal(prevVal => !prevVal); return [val, toggle]; }
第二步:解决ESLint依赖警告
修复bug后,ESLint仍会警告,因为它无法识别自定义Hook返回的toggle函数是稳定的(每次渲染引用不变)。以下是几种可行解决方案:
方案1:用useCallback确保toggle引用稳定
在useToggle内部用useCallback包裹toggle函数,确保其引用在组件生命周期内保持不变。由于React的setState函数本身是稳定的,useCallback的依赖数组可以为空:
import { useState, useCallback, VoidFn } from 'react'; function useToggle(initialValue: boolean): [boolean, VoidFn] { const [val, setVal] = useState<boolean>(initialValue); const toggle = useCallback(() => { setVal(prevVal => !prevVal); }, []); // setVal是稳定的,无需加入依赖 return [val, toggle]; }
修改后,ESLint会识别到toggle是经过记忆的稳定函数,在useCallback中使用时不会再触发警告。
方案2:用ESLint注释忽略单个警告
如果不想修改useToggle的实现,可以在触发警告的行添加注释临时忽略:
const [myBoolVal, toggleMyVal] = useToggle(false); // eslint-disable-next-line react-hooks/exhaustive-deps const handleClick = useCallback(() => toggleMyVal(), []);
注意:这种方法不推荐长期使用,若后续toggleMyVal引用发生变化,可能引发闭包陷阱导致难以排查的bug。
方案3:配置ESLint识别自定义Hook
通过ESLint配置,让react-hooks/exhaustive-deps规则识别你的自定义Hook,将其视为内置Hook分析返回值稳定性。在ESLint配置文件(如.eslintrc.js)中添加:
module.exports = { // 其他配置项... rules: { "react-hooks/exhaustive-deps": ["warn", { additionalHooks: "(useToggle)" }] } };
若有多个自定义Hook,可用正则匹配,比如"(useToggle|useAnotherHook)"。配置后ESLint会自动分析这些Hook的返回值,不再触发不必要的警告。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

