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