【问题标题】:Access state from Event Handler created within React.js UseEffect Hook从 React.js UseEffect Hook 中创建的事件处理程序访问状态
【发布时间】:2019-09-13 00:38:42
【问题描述】:

在我的组件中,我在 useEffect 挂钩中设置了一个事件侦听器:

useEffect(() => {
  const target = subtitleEl.current;
  target.addEventListener("click", () => {
    console.log("click");
    onSubtitleClick();
  });

  return () => {
    target.removeEventListener("click", null);
  };
}, []);

.. 但是当我打电话给onSubtitleClick 时,我的状态是陈旧的——它是原始值。 Example code here。如何从使用 useEffect 设置的事件处理程序访问状态?

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    您的事件侦听器在其定义的环境中注册了一个函数(引用),该函数(引用)具有 count 为 0,并且当发生新的渲染时,您的引用没有被更新,该引用已注册到该元素并且该注册的函数引用仍然知道 count 为 0,即使 count 已更改,但更新的函数未注册,它知道其上下文中的更新值。所以你需要用新的函数引用来更新事件监听器。

    useEffect(() => {
        const target = subtitleEl.current;
        target.addEventListener("click", onSubtitleClick);
    
        return () => {
          console.log("removeEventListener");
          target.removeEventListener("click", onSubtitleClick);
        };
    }, [onSubtitleClick]);
    

    但是,您不需要那些凌乱的代码来实现您现在正在做的事情或类似的事情。您可以在单击时简单地调用传递的函数,而不是通过 ref 附加到元素,而是直接在 jsx 中。

    <div
        className="panelText"
        style={{ fontSize: "13px" }}
        onClick={onSubtitleClick}
        ref={subtitleEl}
      >
        Button2
    </div>
    

    【讨论】:

      【解决方案2】:

      我认为基本上 addeventlistener 创建了一个闭包,它自己版本的count 与父组件分开。一个简单的解决方法是允许 useEffect 函数在更改时重新运行(删除 [] arg):

      useEffect(() => {
        const target = subtitleEl.current;
        target.addEventListener("click", () => {
          console.log("click");
          onSubtitleClick();
        });
      
        return () => {
          target.removeEventListener("click", null);
        };
      }); // removed [] arg which prevents useeffect being run twice
      

      【讨论】:

        猜你喜欢
        • 2021-07-18
        • 2020-01-03
        • 2012-09-19
        • 1970-01-01
        • 2016-03-09
        • 1970-01-01
        • 2020-06-16
        • 2011-11-03
        • 2013-08-15
        相关资源
        最近更新 更多