Javascript 状态更新时使用eventListener进行指数重新呈现
我试图在“keydown”上使用一个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] =
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
传递到依赖项列表,因为函数引用和它的值发生了变化。有点不幸,我会更新答案。我理解你的答案,我在下面发布了工作代码。谢谢你抽出时间!我很感激,伙计:)