如何使用 React useEffect 窗口 removeEventListener [英] How do I window removeEventListener using React useEffect
问题描述
在 React Hooks 文档中,展示了如何在组件的清理阶段移除事件监听器.https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
In React Hooks documents it is shown how to removeEventListener during the component's cleanup phase. https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
在我的用例中,我试图以功能组件的状态属性为条件删除事件监听器.
In my use case, I am trying to removeEventListener conditional to a state property of the functional component.
这是一个永远不会卸载组件但应删除事件侦听器的示例:
Here's an example where the component is never unmounted but the event listener should be removed:
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 上的实时示例)
我看到的问题是 removeEventListener
中的 handleKeyUp
引用在每次渲染组件时都会发生变化.函数handleKeyUp
需要对setCollapsed
的引用,因此它必须被App
括起来.在 useEffect
中移动 handleKeyUp
似乎也触发多次并丢失对原始 handleKeyUp
的引用.
The problem I see is that the handleKeyUp
reference inside removeEventListener
is changing every time the component renders. The function handleKeyUp
needs a reference to setCollapsed
so it must be enclosed by App
. Moving handleKeyUp
inside useEffect
also seems to fire multiple times and lose the reference to the original handleKeyUp
.
如何在不卸载组件的情况下使用 React Hooks 有条件地使用 window.removeEventListener?
How can I conditionally window.removeEventListener using React Hooks without unmounting the component?
推荐答案
您可以将 handleKeyUp
函数放在赋予 useEffect
(这是推荐的方式根据官方文档进行操作),并且仅在 collapsed
为 false 时添加侦听器并返回清理函数.
You can put the handleKeyUp
function inside of the function given to useEffect
(which is the recommended way of doing it according to the official documentation) and only add the listener and return a cleanup function when collapsed
is false.
useEffect(() => {
if (collapsed) {
return;
}
function handleKeyUp(event) {
switch (event.key) {
case "Escape":
setCollapsed(true);
break;
}
}
window.addEventListener("keyup", handleKeyUp);
return () => window.removeEventListener("keyup", handleKeyUp);
}, [collapsed]);
这篇关于如何使用 React useEffect 窗口 removeEventListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!