Javascript 状态更新时使用eventListener进行指数重新呈现

Javascript 状态更新时使用eventListener进行指数重新呈现,javascript,reactjs,dom,dom-events,Javascript,Reactjs,Dom,Dom Events,我试图在“keydown”上使用一个eventListener,它将更新我的状态(一个名为showMenu的布尔值)。 我已经把它放在了useffect上,但是它不能正常工作,我不知道为什么。。。 如果我在useEffect结束时将showMenu放在数组上,它会以指数方式重新呈现组件。 如果我没有将showMenu放在useffect的末尾,则showMenu将只更新一次(从false到true) 下面是以指数方式重新呈现的代码 const [showMenu, setShowMenu] =

我试图在“keydown”上使用一个
eventListener
,它将更新我的状态(一个名为
showMenu
的布尔值)。 我已经把它放在了
useffect
上,但是它不能正常工作,我不知道为什么。。。 如果我在useEffect结束时将
showMenu
放在数组上,它会以指数方式重新呈现组件。 如果我没有将
showMenu
放在
useffect
的末尾,则
showMenu
将只更新一次(从false到true)

下面是以指数方式重新呈现的代码

const [showMenu, setShowMenu] = useState(false);


useEffect(() => {
    window.addEventListener("keydown", (e) => handleMenu(e));
    return () => {
        window.removeEventListener("keydown", (e) => handleMenu(e));
    };
}, [showMenu]);

const handleMenu = (e) => {
    if (e.key == "m") {
        setShowMenu(!showMenu);
    }
};

removeEventListener
接受函数引用,但您每次都在创建匿名函数:

useffect(()=>{
window.addEventListener(“按键向下”,handleMenu);
return()=>{
window.removeEventListener(“向下键”,handleMenu);
};
},[showMenu]);
通过删除匿名函数包装器(也称为eta缩减),addEventListener和removeEventListener可以获得相同的函数引用

或者,如果您只支持现代浏览器,并且希望忽略函数引用的概念,则addEventListener支持
AbortSignal
s:

useffect(()=>{
const ac=新的中止控制器();
addEventListener(“keydown”,(e)=>handleMenu(e),{signal:ac.signal});
return()=>ac.abort();
},[showMenu]);

作为旁注,实际上没有理由将
showMenu
传递到函数的依赖项列表中,我不会传递它。

好吧,我只是找到了它。 useEffect方法不是问题所在。逻辑是好的。 问题在于
(e)=>handleMenu(e)
,我需要直接更改为
handleMenu
。 见下文:

const [showMenu, setShowMenu] = useState(false);

const handleMenu = (e) => {
    if (e.key == "m") {
        setShowMenu(!showMenu);
    }
};

useEffect(() => {
    window.addEventListener("keydown", handleMenu);
    return () => {
        window.removeEventListener("keydown", handleMenu);
    };
}, [showMenu]);

感谢Benjamin给了我答案:我需要传递我的handleMenu函数引用,而不是使用
(e)=>
语法,该语法每次都基于我的handleMenu函数创建一个新函数,它解释了指数渲染:)

对不起,我不明白。是否需要将
手柄菜单
放在
useffect
的末尾?如果这是你的意思,我还有指数级的渲染。。。也许我需要使用另一个钩子?@feyndev经过再三考虑(添加了一条注释),我不会将任何内容作为依赖项列表传递给
useffect
,该列表是“在依赖项发生变化时运行此效果”,因为您的效果不是有状态的(它只是附加了一个侦听器,状态在应用程序中)只有在组件卸载时才更改内容时设置侦听器没有实际意义。但是,当按下“m”键时,不会调用该函数。。状态仅更改一次。如何在每次键入键时更新状态而不使用useEffect?当执行手动编辑DOM等副作用时,需要使用useEffect。我认为您必须将
showMenu
传递到依赖项列表,因为函数引用和它的值发生了变化。有点不幸,我会更新答案。我理解你的答案,我在下面发布了工作代码。谢谢你抽出时间!我很感激,伙计:)