Here is my code.
import { useState } from "react";
const App = () => {
const [shout, setShout] = useState(true);
const [message, setMessage] = useState("hello world!");
window.addEventListener("keypress", e => {
console.log(shout);
if(e.key === "a" && shout === true) {
setMessage(message.toUpperCase())
}
});
return (
<div>
<h1>{message}</h1>
<button onClick={() => setShout(!shout)}>disable keypress!</button>
<button onClick={() => setMessage(message.toLowerCase())}>to lower case</button>
</div>
)
}
export default App;
When I press the a button on my keyboard the message is transformed to uppercase if the disable keypress button is not clicked. If it's clicked pressing a key should not upper case the message.
When I console.log the shout variable in the eventListner callback it seems like the shout variable is set from true to false simultaneously.
How can I prevent it?
You need to use useEffect to add side effects in react and also to make sure your listener is removed once the component un-mounts.
Also I prefer document instead of window but I don't think that makes a difference.
import { useState, useEffect } from "react";
const App = () => {
const [shout, setShout] = useState(true);
const [message, setMessage] = useState("hello world!");
useEffect(() => {
const listener = (e) => {
if(e.key === "a" && shout === true) {
console.log(e.key, shout);
setMessage(message.toUpperCase());
}
};
document.addEventListener("keypress", listener);
return () => {
document.removeEventListener('keypress', listener);
};
}, [shout, message]);
return (
<div>
<h1>{message}</h1>
<button onClick={() => setShout(!shout)}>disable keypress!</button>
<button onClick={() => setMessage(message.toLowerCase())}>to lower case</button>
</div>
)
}
export default App;