the*_*mer 5 immutability keydown reactjs react-hooks
请看一下这个代码片段。
function App() {
useEffect(() => {
document.addEventListener('keydown', onKeyDown);
}, []);
const onKeyDown = e => {
setKeyMap({ ...keyMap, [e.keyCode]: true });
};
const [keyMap, setKeyMap] = useState({});
// JSON.stringify gives only one key-value pair
return (
<div className="App">
<h1>Hello {JSON.stringify(keyMap)}</h1>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
因此,使用useEffect,我keydown只向事件添加一次事件侦听器。这显然与 componentDidMount 类似,因为这只发生一次。
在 keydown 事件的事件处理程序中,我尝试添加所有被按下为 true 的键码。
假设我按“a”,那么我的 keyMap 应该如下所示:
{
"65": true
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我按“b”,那么我的 keyMap 应该如下所示:
{
"65": true,
"66": true
}
Run Code Online (Sandbox Code Playgroud)
但发生的事情是这样的:
{
"66": true
}
Run Code Online (Sandbox Code Playgroud)
为什么我无法改变以前的状态并添加到它?就像我以前有“65”作为键,但是当我按下键盘上的另一个键时,这个“65”键值突然消失了。也就是说,在任何给定点,one由于某种原因,只有键值对存在。我希望能够多次添加到这个对象(我的意思是 keyMap 对象)。运算...符(传播)不起作用吗?
useEffect(() => {
document.addEventListener('keydown', onKeyDown);
}, []);
Run Code Online (Sandbox Code Playgroud)
由于第二个参数为空数组,因此仅在组件首次渲染时运行一次。onKeyDown函数有一个对当时状态的引用,所以keyMapinsetKeyMap({ ...keyMap, [e.keyCode]: true });指的是一个空对象。每当调用此密钥处理程序时,它都会将状态设置为空对象,加上最新的密钥。
相反,您希望它使用最新状态。对于如何执行此操作,您有两个主要选项
1)不要跳过效果。这样,您将始终拥有一个具有最新状态的事件侦听器。请记住返回一个拆卸函数,这样就不会发生事件侦听器泄漏:
useEffect(() => {
const onKeyDown = e => {
setKeyMap({ ...keyMap, [e.keyCode]: true });
};
document.addEventListener('keydown', onKeyDown);
return () => document.removeEventListener('keydown', onKeyDown);
}); // You could also pass [keyMap] as the second param to skip irrelevant changes
Run Code Online (Sandbox Code Playgroud)
2)或者,使用setKeyMap的函数版本。它会向您传递该状态的最新值。
const onKeyDown = e => {
setKeyMap(prevKeyMap => ({ ...prevKeyMap, [e.keyCode]: true }));
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3772 次 |
| 最近记录: |