React:窗口事件订阅
我正在研究 React 并尝试创建某种键盘训练应用程序。
我想向窗口对象添加一个 keypress
事件监听器来获取字母,然后更新我使用 useState()
挂钩创建的状态。
因此,我在 useEffect
挂钩中添加了事件侦听器。与自定义处理程序。但在这种情况下,setPhrase
函数似乎效果不佳。
预期结果: 在每个正确的按键后,按 phrase.writing
将此按键添加为文本,phrase.left
将此字母作为子字符串;
实际结果: 状态每次都会更新,因此在 setPhrase
调用后状态不会更新
代码:
export default () => {
const [initialPhrase] = useState("Test Phrase");
const [phrase, setPhrase] = useState({
left: initialPhrase,
written: "",
});
const handleKeyPress = (event) => {
const requiredLetter = phrase.left.charAt(0);
if (requiredLetter === event.key) {
setPhrase({
written: phrase.written + event.key,
left: phrase.left.substring(1, phrase.left.length),
});
}
console.debug(phrase, requiredLetter, event.key, phrase);
};
useEffect(() => {
window.addEventListener("keypress", handleKeyPress);
return () => window.removeEventListener("keypress", handleKeyPress);
}, []);
return (
<div>
<p className="phrase">
<span className="phrase--part phrase--part__written">
{phrase.written}
</span>
<span className="phrase--part phrase--part__left">{phrase.left}</span>
</p>
</div>
);
};
Playground: https://stackblitz.com/edit/react-qgbjaf?file= src/index.js
注意:如果将此处理程序放置到组件内的任何元素,它将按预期工作
I am getting into React and trying to create some kind of keyboard trainer app.
I want to add a keypress
event listener to the window object to get the letters, and then update the state I created with useState()
hook.
So I add the event listener inside useEffect
hook. with the custom handler. But the setPhrase
function doesn't seem to work well in this case.
Expected result:
After each correct key press the phrase.written
to add this key as text, phrase.left
to substring by this letter;
Actual result:
State is renewed every time, so the state doesn't update after setPhrase
call
The code:
export default () => {
const [initialPhrase] = useState("Test Phrase");
const [phrase, setPhrase] = useState({
left: initialPhrase,
written: "",
});
const handleKeyPress = (event) => {
const requiredLetter = phrase.left.charAt(0);
if (requiredLetter === event.key) {
setPhrase({
written: phrase.written + event.key,
left: phrase.left.substring(1, phrase.left.length),
});
}
console.debug(phrase, requiredLetter, event.key, phrase);
};
useEffect(() => {
window.addEventListener("keypress", handleKeyPress);
return () => window.removeEventListener("keypress", handleKeyPress);
}, []);
return (
<div>
<p className="phrase">
<span className="phrase--part phrase--part__written">
{phrase.written}
</span>
<span className="phrase--part phrase--part__left">{phrase.left}</span>
</p>
</div>
);
};
Playground:
https://stackblitz.com/edit/react-qgbjaf?file=src/index.js
Note: if you place this handler to any element inside component, it is going to work just as expected
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是在短语状态更新后,handleKeyPress 方法没有更新。因此,您需要将handleKeyPress方法添加到useEffect依赖中。现在,在每个短语状态更新之后,该方法都会获取短语 Stackblitz fork 的正确状态
: https://stackblitz.com/edit/react-bx5qp7?file=src/index.js
The problem is that the handleKeyPress Method is not updated after the phrase state updated. Therefore, you need to add the handleKeyPress method to the useEffect dependency. Now after each phrase state update, the method gets the correct state of phrases
Stackblitz fork: https://stackblitz.com/edit/react-bx5qp7?file=src/index.js
在事件处理程序方法中,您无法达到更新的状态,因为状态变量不会在 EventListener 内更新自身。只需像这样使用 useRef :
in your event handler method you cant reach the updated state, because state variables don't update itself inside an EventListener. just use useRef like this: