javascript - 当通过钩子(Hook)传递时,setState 函数是否应该是 useEffect 的依赖项

标签 javascript reactjs react-hooks closures

所以,我偶然发现了这种奇怪的情况:

我有一个全局 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/

相关文章:

javascript - 如何使 Google map 标记成为简单的 URL 链接?

javascript - 使用 React 根据另一个下拉列表更新选择的选项

javascript - 当我使用trackballcontrols.js时关于三个.js的问题

javascript - 如何在加载屏幕上更改为上传图片创建的 CSS 圆圈

javascript - 确保 Accordion 选项卡是独立的

javascript - 如何在 react.js 中包含 html View 文件

node.js - 如何在react JS或React-Redux JS中验证CloudKit JS

javascript - 如果 styleName 存在,则检查 React 组件

javascript - 使用 Context API 传递数据时值未定义

javascript - 在 Prop 中传递对象时避免重新渲染 child