When I set a handler using OnClick it works fine and console.log always use the actual state. But when I use AddEventListener it works only once and then use the old state.
What the reason for than behaviour??
see the link https://codesandbox.io/s/blazing-star-wf3c9?file=/src/App.js
P.S Using [count] as useEffect dependence fix it, but it just create new listener each time, don't think that the right way to do this
You have a closure issue.
In fact in each render your component going to create a new function showCount that you fixed the count.
For exemple:
In 1st render you create a function showCount that you fixed count = 1.
In your 2nd render you create a function showCount that you fixed count = 2.
In your 3 render you create a function showCount that you fixed count = 3.
The issue is that you are not changing the showcount when your count changes like this.
useEffect(() => {
let buttonShow = document.querySelector(".buttonShow");
buttonShow.addEventListener("click", showCount, true);
return () => {
buttonShow.removeEventListener("click", showCount, true);
};
}, [count]);
You can see the log count 2 because the reference of the count doesn't change when you use incremental.
I think the best solution is to you use a Component class:
import React from "react";
class CounterAddEvent extends React.PureComponent {
state = {
count: 1
};
componentDidMount() {
let buttonShow = document.querySelector(".buttonShow");
buttonShow.addEventListener("click", this.showCount, true);
}
componentWillUnmount() {
let buttonShow = document.querySelector(".buttonShow");
buttonShow.removeEventListener("click", this.showCount, true);
}
increaseCount = () => {
this.setState({ count: this.state.count + 1 });
};
showCount = () => {
console.log(this.state.count);
};
render() {
return (
<div>
<button onClick={this.increaseCount} className="input">
increase
</button>
<button>{this.state.count}</button>
<button className="buttonShow">Show console</button>
</div>
);
}
}
export default CounterAddEvent;