简体   繁体   English

来自在React.js UseEffect挂钩中创建的事件处理程序的访问状态

[英]Access state from Event Handler created within React.js UseEffect Hook

In my component I'm setting up an event listener within the useEffect hook: 在我的组件中,我要在useEffect挂钩中设置一个事件侦听器:

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

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

.. but when I call onSubtitleClick , my state is stale - it's the original value. ..但是当我调用onSubtitleClick ,我的状态是陈旧的-这是原始值。 Example code here . 示例代码在这里 How can I access state from the event handler that was setup with the useEffect? 如何从使用useEffect设置的事件处理程序中访问状态?

Your event listener registers a function (reference) which has count as 0 in the environment it is defined and when a new render happens, your reference is not being updated which is registered with that element and that registered function reference still knows that count is 0 even though count has been changed but that updated function was not registered which knows the updated value in its context. 您的事件侦听器在定义的环境中注册了一个count为0的函数(引用),并且当发生新的渲染时,您的引用没有更新,该引用已注册到该元素,并且该注册的函数引用仍然知道计数为0即使计数已更改,但未注册更新的函数,该函数在其上下文中知道更新的值。 So you need to update event listener with new function reference. 因此,您需要使用新的函数引用来更新事件侦听器。

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

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

However, you don't need that messy code to achieve what you are doing now or similar stuff. 但是,您不需要那些凌乱的代码即可实现您现在正在做的事情或类似的工作。 You can simply call that passed function on click and don't attach to element through ref but directly in jsx. 您可以在单击时简单地调用该传递的函数,而不必通过ref而是直接在jsx中附加到元素。

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

I think basically the addeventlistener creates a closure with its own version of count separate to the parent component's. 我认为基本的addEventListener创建了自己的版本的封闭count独立于父组件的。 A simple fix is to allow the useEffect function to rerun on changes (remove the [] arg): 一个简单的解决方法是允许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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM