所以,我偶然发现了这种奇怪的情况:
我有一个全局 React 上下文提供程序,提供一个全局状态,就像这样
const Context = createContext();
const ContextProvider = ({children}) => {
const [state, setState] = useState('');
return <Context.Provider value={{state, setState}}>{children}</Context.Provider>
}
const useMyState = () => {
const {state, setState} = useContext(Context);
return {
state,
setState
}
}
const Component = () => {
const {setState} = useMyState();
useEffect(() => {
elementRef.addEventListener('click', () => {
setState('someState');
});
return () => {
elementRef.removeEventListener('click', () => null);
}
},[])
return <>
// ...
</>
}
eslint
建议将我的 setState
添加到 useEffect
的依赖数组中,
useEffect(() => {
elementRef.addEventListener('click', () => {
setState('someState');
});
},[setState])
我猜这可能与 useMyState.ts
文件中上下文的解构有某种关系
但这感觉有点奇怪和不直观......
我的问题是 setState
是否真的需要依赖数组?如果是,为什么?
最佳答案
my question is is the
setState
really required inside the dependency array?
不,它不是,但 ESLint 不知道这一点,因为它无法知道您正在使用的上下文对象的 setState
成员是否稳定。 您知道(因为 useState
保证 setter 是稳定的,并且您通过上下文和您的 useMyState
钩子(Hook)逐字传递它) , 但 ESLint 不知道。
您可以将它添加为依赖项以使 ESLint 满意(如果您已经提供了一个数组,它不会有任何区别,因为 setter 永远不会改变;如果您不是 提供一个数组),或者你可以在注释中告诉 ESLint 跳过检查该代码,或者你可以关闭规则(但是很容易错过依赖项,所以要小心你这样做)。
(如果您没有提供数组 [因为您希望效果在每次渲染后运行],添加一个带有 setter 的数组将阻止这种情况发生,因此您需要选择在这种情况下禁用 ESLint 错误。或者有一些棘手的解决方案,比如使用一个数值不断增加的 ref。:-) )
不过,该代码存在问题。它重复地向元素添加新的事件监听器而不删除它们,因为没有 no 依赖数组,每次组件呈现时都会调用 useEffect
回调,并且您正在创建每次都有一个新的事件处理函数,所以它们会堆积起来。
因此,您需要使 elementRef.current
成为依赖项,并且需要一个清理回调:
const Component = () => {
const {setState} = useMyState();
useEffect(() => {
const handler = () => {
setState("someState");
};
const element = elementRef.current;
// Note −−−−−−−−−−−−−−−−−−^^^^^^^^
element.addEventListener("click", handler);
return () => {
element.removeEventListener("click", handler);
};
}, [elementRef.current]); // <== Optionally add `setState` to this
return <>
// ...
</>;
};
关于javascript - 当通过钩子(Hook)传递时,setState 函数是否应该是 useEffect 的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71942624/