如何使用反应钩子useState添加到对象?
How to add to object using react hook useState?
请看一下这段代码。
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 因为这只发生一次。
在 keydown 事件的事件处理程序中,我试图添加所有被按下为真的键码。
假设我按下 'a',那么我的 keyMap 应该如下所示:
{
"65": true
}
现在,如果我按 'b',那么我的 keyMap 应该如下所示:
{
"65": true,
"66": true
}
但实际情况是这样的:
{
"66": true
}
为什么我无法改变以前的状态并添加到它?就像我之前将“65”作为键,但是当我按下键盘上的另一个键时,这个“65”键值突然消失了。也就是说,在任何给定点,由于某种原因只存在 one
键值对。我希望能够根据需要多次添加到这个对象(我的意思是 keyMap 对象)。 ...
运算符(传播)是否不起作用?
useEffect(() => {
document.addEventListener('keydown', onKeyDown);
}, []);
由于第二个参数为空数组,因此仅在组件首次呈现时获得一次 运行。 onKeyDown函数在那个时候有一个状态的引用,所以setKeyMap({ ...keyMap, [e.keyCode]: true });
中的keyMap
指的是一个空对象。每次调用此密钥处理程序时,它都会将状态设置为一个空对象,加上最新的密钥。
相反,您希望它使用最新状态。您有两个主要选项来执行此操作
1) 不要跳过效果。这样,您将始终拥有一个具有最新状态的事件侦听器。记得 return 一个拆卸函数,这样你就没有事件监听器泄漏:
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
:
请看一下这段代码。
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 因为这只发生一次。
在 keydown 事件的事件处理程序中,我试图添加所有被按下为真的键码。
假设我按下 'a',那么我的 keyMap 应该如下所示:
{
"65": true
}
现在,如果我按 'b',那么我的 keyMap 应该如下所示:
{
"65": true,
"66": true
}
但实际情况是这样的:
{
"66": true
}
为什么我无法改变以前的状态并添加到它?就像我之前将“65”作为键,但是当我按下键盘上的另一个键时,这个“65”键值突然消失了。也就是说,在任何给定点,由于某种原因只存在 one
键值对。我希望能够根据需要多次添加到这个对象(我的意思是 keyMap 对象)。 ...
运算符(传播)是否不起作用?
useEffect(() => {
document.addEventListener('keydown', onKeyDown);
}, []);
由于第二个参数为空数组,因此仅在组件首次呈现时获得一次 运行。 onKeyDown函数在那个时候有一个状态的引用,所以setKeyMap({ ...keyMap, [e.keyCode]: true });
中的keyMap
指的是一个空对象。每次调用此密钥处理程序时,它都会将状态设置为一个空对象,加上最新的密钥。
相反,您希望它使用最新状态。您有两个主要选项来执行此操作
1) 不要跳过效果。这样,您将始终拥有一个具有最新状态的事件侦听器。记得 return 一个拆卸函数,这样你就没有事件监听器泄漏:
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
: