So, What I'm trying to do is add an event listener to a button that when pressed takes the value of a state and console log it. But the logged value never updates even after the multiple setState calls.
useEffect(() => {
const seamCarve = document.getElementById("process");
seamCarve.addEventListener("click", (e) => {
console.log(seamValue);
});
}, []);
And then there's the button that triggers it
<div id="seamvalue">
<Typography variant="h6" align="center">
Seams Reduction:<span id="valueOfSeam"> {seamValue} </span>
</Typography>
</div>
<Button
id="leftslider"
variant="contained"
color="primary"
onClick={() =>
seamValue - 10 > 0 ? setSeamValue(seamValue - 10) : setSeamValue(0)
}
>
<Typography>{"<"}</Typography>
</Button>
<Button
id="rightslider"
variant="contained"
color="primary"
onClick={() => setSeamValue(seamValue + 10)}
>
<Typography>{">"}</Typography>
</Button>
<Button id="process" variant="contained" color="primary">
<Typography>Carve</Typography>
</Button>
The value changes as I click on the sliders but when I press the Button with id="process" with an event listener associated with it, it only prints 20 even after updating the state.
Don't use native DOM methods like addEventListener in React if at all possible - instead, work within React to achieve the same effect. It'll make a whole lot more sense and will require less convoluted code.
Put the click listener in the JSX syntax returned instead.
<Button
id="process"
variant="contained"
color="primary"
onClick={() => console.log(seamValue)}
>
<Typography>Carve</Typography>
</Button>
If you absolutely cannot attach the click listener via React for some reason, then attach the listener again when the state changes. Also note that in order to start a function, you need a { after the =>, unless you're using concise return (which you aren't here).
useEffect(() => {
const seamCarve = document.getElementById("process");
const handler = () => {
console.log(seamValue);
};
seamCarve.addEventListener('click', handler);
return () => seamCarve.removeEventListener('click', handler);
}, [seamValue]);
State variables don't update itself inside an EventListener. If you want to update and access some state inside an EventListener, look into useRef. Also, you need to replace your 2nd useState statement with useEffect since that's what you wanted to implement. A relevant post that should answer your question: Wrong React hooks behaviour with event listener
EDIT: as @CertainPerformance stated, event listeners like onClick can be directly used inside the jsx. My answer applies to the use of event listeners on the document.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With