使用 useEffect 反应 addEventListener 问题

React addEventListener issue with useEffect

我正在制作一个带有 React 的自定义图像查看器,我想使用键盘的左箭头和右箭头来实现图像导航

注:currentId为当前可见的图片id

useEffect(() => {
  document.addEventListener("keydown", function (event) {
    if (event.key === "ArrowRight") {
      setLoaded(false);
      if (currentId + 1 < props.imgs.length) {
        console.log("right");
        setcurrentId(currentId + 1);
      } else if (currentId + 1 === props.imgs.length) {
        setcurrentId(0);
      }
    } 
    
    if (event.key === "ArrowLeft") {
      setLoaded(false);
      if (currentId - 1 >= 0) {
        console.log("left");
        setcurrentId(currentId - 1);
      } else if (currentId - 1 === -1) {
        setcurrentId(props.imgs.length - 1);
      }
    }
  });
}, [currentId]);

现在的问题是,当我按下键盘 right/left 箭头键时 console.log() 每次都使用随机数执行多次,我知道每次状态更新可能是 运行 但不知道如何修复它。

虽然当我将 [currenId] 添加到 useEffect 时,图像导航可以正常工作,但控制台仍然看起来像这样,使导航变慢

我也尝试过不使用 [currentId] 作为第二个参数。当我这样做时,它会记录这个

并在 ArrowRight 上按下它将 currentId 设置为 1 并且日志的权利只有一次但是当我再次按下时没有做任何事情

并且当按下 ArrowLeft 时,它将 currentId 设置为数组的长度 props.imgs - 1 例如:- props.imgs.length - 1 和日志的 nothing

你一遍又一遍地注册监听器。 React 关于 useHook 的文档提到了如何 clean up 某些事情,这正是事件监听器所需要的:

useEffect(() => {
    const listener = function(event) {
        // ...
    };
    document.addEventListener('keydown', listener);
    return () => {
        // This function gets called when the "effect wears off"
        // which means we need to unregister the listener
        document.removeEventListener('keydown', listener);
    };
}, [currentId]);

[currentId] 使得 React 只在 currentId 发生变化时调用钩子。 React 还确保每当组件被卸载,或者钩子将要为同一个组件重新执行时,“清理函数”就会被调用。清理函数基本上是您在钩子中 return 的任何函数。如果您不 return any,则不会调用清理函数。