从React.js UseEffect Hook中创建的事件处理程序访问状态

问题描述 投票:0回答:2

在我的组件中,我在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
2个回答
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>

0
投票

我认为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
© www.soinside.com 2019 - 2024. All rights reserved.