Reputation: 65
in this very simple demo
import { useState } from 'react';
function App() {
const [check, setCheck] = useState(false);
console.log('App component Init');
return (
<div>
<h2>Let's get started! </h2>
<button
onClick={() => {
setCheck(true);
}}
>
ClickMe
</button>
</div>
);
}
export default App;
i get one log on app init,
upon the first click (state changes from false to true) i get another log as expected.
But on the second click i also get a log , although the state remains the same.(interstingly the ReactDevTools doesn't produce the highlight effect around the component as when it is rerendered)
For every following clicks no log is displayed.
Why is this extra log happening. Here is a stackblitz demo: https://stackblitz.com/edit/react-ts-wvaymj?file=index.tsx Thanks in advance
Upvotes: 2
Views: 492
Reputation: 202605
Given
i get one log on app init,
upon the first click (state changes from false to true) i get another log as expected.
But on the second click i also get a log , although the state remains the same.(interstingly the ReactDevTools doesn't produce the highlight effect around the component as when it is rerendered)
For every following clicks no log is displayed.
And your question being
Why is this extra log happening?
Check the useState
Bailing Out of a State Update section (emphasis mine):
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the
Object.is
comparison algorithm.)Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go “deeper” into the tree. If you’re doing expensive calculations while rendering, you can optimize them with
useMemo
.
The answer to your question is essentially, "It's just the way React and the useState
hook work." I'm guessing the second additional render is to check that no children components need to be updated, and once confirmed, all further state updates of the same value are ignored.
Upvotes: 3
Reputation: 496
If you console log check you can see...
The first click you will get check
is true
-> check state change from false (init) => true (click) => state change => view change => log expected.
The second click => check state is true (from frist click) => true => state not change => view not render.
So. you can try
setCheck(!check);
Upvotes: 0