在React Hooks文档中,显示了如何在组件的清理阶段删除removeEventListener。https://reactjs.org/docs/hooks- reference.html#conditionally-firing-an-effect
在我的用例中,我试图以功能组件的state属性为条件的removeEventListener。
这是一个示例,其中从不卸载组件,但应删除事件侦听器:
function App () { const [collapsed, setCollapsed] = React.useState(true); React.useEffect( () => { if (collapsed) { window.removeEventListener('keyup', handleKeyUp); // Not the same "handleKeyUp" :( } else { window.addEventListener('keyup', handleKeyUp); } }, [collapsed] ); function handleKeyUp(event) { console.log(event.key); switch (event.key) { case 'Escape': setCollapsed(true); break; } } return collapsed ? ( <a href="javascript:;" onClick={()=>setCollapsed(false)}>Search</a> ) : ( <span> <input placeholder="Search" autoFocus /> <a href="javascript:;">This</a> <a href="javascript:;">That</a> <input placeholder="Refinement" /> </span> ); } ReactDOM.render(<App />, document.body.appendChild(document.createElement('div')));
(实时示例位于https://codepen.io/caqu/pen/xBeBMN)
我看到的问题是,每次组件渲染时,handleKeyUp内部引用removeEventListener都会发生变化。该函数handleKeyUp需要引用,setCollapsed因此必须用括起来App。搬进handleKeyUp里面useEffect也似乎会触发多次,并且失去了对原件的引用handleKeyUp。
handleKeyUp
removeEventListener
setCollapsed
App
useEffect
如何在不卸载组件的情况下使用React Hooks有条件地window.removeEventListener?
您可以将handleKeyUp函数放在给定的函数内部,useEffect并且仅添加侦听器,并且在collapsed为false 时返回清除函数。
collapsed
useEffect(() => { if (!collapsed) { function handleKeyUp(event) { switch (event.key) { case "Escape": setCollapsed(true); break; } } window.addEventListener("keyup", handleKeyUp); return () => window.removeEventListener("keyup", handleKeyUp); } }, [collapsed]);