I'm a beginner to React JS.
I faced this weird situation,
const [counter, setCounter] = useState(0);
const incrementCounter = () => {
setCounter(counter 1);
console.log(counter, "Log inside the function");
};
useEffect(() => {
console.log(counter, "Log inside the useEffect");
}, [counter]);
return (
<div>
<h1>{counter}</h1>
<button onClick={incrementCounter}>Increment</button>
</div>
);
So when incrementCounter
function is triggered counter value will be increased by 1 and right after that I'm logging the value in the console. But it displays the value as 0. When I use the useEffect
hook to check the changes of count
state it I'm getting the correct value as 1 when I log the count value
inside the useEffect
scope. What is the reason for not displaying in incrementCounter
function and the reason for displaying the correct value inside the useEffect
hook. Please I need a clear explanation, Try not to downvote thanks.
CodePudding user response:
States value will change only after the component has rendered.
In this case the log inside the function will keep the state value even after the SetCounter, once it completes the component will render again.
The useEffect is triggered when the state has changed on such render so it shows the new value.
CodePudding user response:
A new incrementCounter
function object is being redefined with every render. Each time it is defined, its own internal counter
is based on the counter
state is at that point. The counter
within that particular incrementCounter
function object is stale and doesn't get updated anymore.
CodePudding user response:
according to React docs
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in flushSync, but this may hurt performance.
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.