reactjs - 如何使用 React useEffect 窗口 removeEventListener
问题描述
在 React Hooks 文档中,展示了如何在组件的清理阶段移除事件监听器。https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
在我的用例中,我试图以功能组件的状态属性为条件删除EventListener。
这是一个永远不会卸载组件但应删除事件侦听器的示例:
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
。
如何在不卸载组件的情况下有条件地使用 React Hooks window.removeEventListener?
解决方案
您可以将handleKeyUp
函数放在给定的函数内部useEffect
(根据官方文档,这是推荐的做法collapsed
),并且仅在为 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]);
推荐阅读
- java - log4j DailyRollingFileAppender 滚动两次
- symfony5 - EasyAdmin - 删除操作,同时删除一个物理文件
- javascript - 如何在 laravel 中使用 sweetalert 使用问题提醒?
- c++ - 尽管包含了包含文件,但此范围事件中未声明某些类型
- botframework - 调度程序 LUIS 应用是否可以用作另一个调度程序 LUIS 模型的一部分?
- javascript - 从 Firestore 异步获取数据
- javascript - FlatList React Native中的平滑scrollToOffset
- node.js - 异步错误未到达 Express 错误中间件
- c++ - std::chrono 比较没有日期
- c# - 在 C# 中使用 LINQ to SQL 在 Cosmos DB 中查询动态键嵌套字典结构