为何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
相关产品推荐
相关产品推荐

