【问题标题】:React.js State not updating in Event Listener in useEffect HookReact.js 状态未在 useEffect Hook 中的事件侦听器中更新
【发布时间】:2021-07-18 12:00:29
【问题描述】:

所以,我要做的是向按钮添加一个事件侦听器,当按下该按钮时,它会获取状态的值并在控制台记录它。但即使在多次 setState 调用之后,记录的值也不会更新。

    useEffect(() => {
      const seamCarve = document.getElementById("process");
    
      seamCarve.addEventListener("click", (e) => {
        console.log(seamValue);
      });
    }, []);

然后是触发它的按钮

          <div id="seamvalue">
            <Typography variant="h6" align="center">
              Seams Reduction:<span id="valueOfSeam"> {seamValue} </span>
            </Typography>
          </div>
    
          <Button
            id="leftslider"
            variant="contained"
            color="primary"
            onClick={() =>
              seamValue - 10 > 0 ? setSeamValue(seamValue - 10) : setSeamValue(0)
            }
          >
            <Typography>{"<"}</Typography>
          </Button>
    
          <Button
            id="rightslider"
            variant="contained"
            color="primary"
            onClick={() => setSeamValue(seamValue + 10)}
          >
            <Typography>{">"}</Typography>
          </Button>
    
          <Button id="process" variant="contained" color="primary">
            <Typography>Carve</Typography>
          </Button>

当我单击滑块时,值会发生变化,但是当我按下带有关联事件侦听器的 id="process" 按钮时,即使在更新状态后它也只会打印 20。

【问题讨论】:

    标签: javascript reactjs react-state-management


    【解决方案1】:

    状态变量不会在 EventListener 中自行更新。如果您想更新和访问 EventListener 中的某些状态,请查看 useRef。此外,您需要用useEffect 替换您的第二个useState 语句,因为这是您想要实现的。应该回答您的问题的相关帖子:Wrong React hooks behaviour with event listener

    编辑:正如@CertainPerformance 所说,像onClick 这样的事件监听器可以直接在jsx 中使用。我的回答适用于在document 上使用事件监听器。

    【讨论】:

      【解决方案2】:

      如果可能的话,不要在 React 中使用像 addEventListener 这样的原生 DOM 方法 - 相反,在 React 中使用 以达到相同的效果。它会更有意义,并且需要更少复杂的代码。

      将点击监听器放在返回的 JSX 语法中。

      <Button
          id="process"
          variant="contained"
          color="primary"
          onClick={() => console.log(seamValue)}
      >
          <Typography>Carve</Typography>
      </Button>
      

      如果由于某种原因你绝对不能通过 React 附加点击监听器,那么当状态改变时再次附加监听器。另请注意,为了启动一个函数,您需要在 =&gt; 之后添加一个 {,除非您使用的是简洁返回(您不在这里)。

      useEffect(() => {
          const seamCarve = document.getElementById("process");
          const handler = () => {
              console.log(seamValue);
          };
          seamCarve.addEventListener('click', handler);
          return () => seamCarve.removeEventListener('click', handler);
      }, [seamValue]);
      

      【讨论】:

      • 哦,我没有注意到 OP 正在使用“onClick”事件监听器。那么我的回答只适用于document.addEventListener的一般用途。
      • 我遇到的问题是我需要访问某些我无法访问的元素。
      • @Akash 为什么你不能访问它?如果您需要的状态不在您单击按钮的组件中,请将状态放在父组件中并向下传递。
      • 我使用了一种非常非反应性的方式来添加一堆事件侦听器,因为我主要使用 HTML Canvas,并且我需要比包装器提供的更大的灵活性。没有依赖关系的 useEffect 钩子添加了加载图像然后在画布上绘制加载的图像的事件侦听器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      • 2019-09-13
      • 2020-05-09
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多