You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何useEffect中的事件处理函数handler会多次执行?

问题解答

首先要明确:你的useEffect确实只执行了一次(因为依赖项是[],仅在组件首次挂载时运行),但里面的handler函数多次执行的原因很简单——它被绑定成了document的keydown事件监听器,每次你按下键盘上的任意按键,浏览器都会触发keydown事件,进而调用这个handler函数。

再拆解下你的代码逻辑:

  • 每次触发keydown事件,handler就会把当前按键的keyCode推入内部的keys数组
  • 接着截取数组最后3位拼接成字符串,用来匹配特定的按键组合(比如1716113对应某组快捷键)
  • 每按一次键盘就会走一遍这些逻辑,所以你会看到handler多次运行

另外还有个隐藏问题需要注意:keys数组定义在useEffect内部,属于闭包变量——每次触发handler时,引用的都是组件首次挂载时创建的那个数组,这会导致它持续累积所有按键的keyCode,如果组件长期存在,这个数组会越来越大,可能造成不必要的内存占用。如果你的需求是只保留最近3次按键,可以改用状态来管理,避免闭包陷阱:

// 组件顶部先定义状态
const [keys, setKeys] = useState([]);

useEffect(() => {
  const handler = (e) => {
    setKeys(prevKeys => {
      // 只保留最近3个按键的keyCode
      const newKeys = [...prevKeys, e.keyCode].slice(-3);
      const getItemsFiltered = newKeys.join("");
      
      if (getItemsFiltered === "1716113") {
        setShow(true);
      }
      if (getItemsFiltered === "1716114") {
        document.getElementById("textField")?.focus();
      }
      return newKeys;
    });
  };

  document.addEventListener("keydown", handler, false);
  return () => document.removeEventListener("keydown", handler, false);
}, []);

内容的提问来源于stack exchange,提问作者Saeed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:20:55