如何使用反应钩子使用状态添加到对象?



请看一下这段代码片段。

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>
);
}

因此,使用useEffect,我只向keydown事件添加一个事件侦听器一次。这显然类似于 componentDidMount,因为这只发生一次。

在键关闭事件的事件处理程序中,我正在尝试添加所有按下为 true 的键码。

所以说我按"a",那么我的键盘映射应该看起来像这样:

{
"65": true
}

现在,如果我按"b",那么我的键盘映射应该看起来像这样:

{
"65": true,
"66": true
}

但正在发生的事情是这样的:

{
"66": true
}

为什么我无法改变以前的状态并添加它?就像我以前用"65"作为键一样,但是当我按键盘上的另一个键时,突然这个"65"键值消失了。也就是说,在任何给定点,由于某种原因,只有one键值对存在。我希望能够根据需要多次添加到此对象(我的意思是keyMap对象(。...运算符(点差(不工作吗?

useEffect(() => {
document.addEventListener('keydown', onKeyDown);
}, []);

由于空数组作为第二个参数,因此在组件首次呈现时,它只会运行一次。onKeyDown 函数引用当时的状态,因此setKeyMap({ ...keyMap, [e.keyCode]: true });中的keyMap引用空对象。每当调用此键处理程序时,它都会将状态设置为空对象以及最新的键。

相反,您希望它使用最新状态。您有两个主要选项来执行此操作

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

2( 或者,使用 setKeyMap 的函数版本。它将传递状态的最新值。

const onKeyDown = e => {
setKeyMap(prevKeyMap => ({ ...prevKeyMap, [e.keyCode]: true }));
};

你只需要像这样将 onKeyDown 函数移动到 useEffect 钩子内部。注意我在依赖项数组中添加了 useEffect 钩子的keyMap

https://codesandbox.io/s/red-sun-23bmu?fontsize=14

相关内容

  • 没有找到相关文章

最新更新