Reputation: 530
Here's my code for App.js
function App() {
console.log('Rendering the App component');
const [someBooleanVar, updateBooleanVar] = React.useState(false);
console.log(someBooleanVar);
const clickHandler = () => {
console.log('In clickHandler');
console.log(someBooleanVar);
updateBooleanVar(true);
};
return (
<div className="app">
<h1>Test App</h1>
<button onClick={clickHandler}>Toggle</button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="app"></div>
When the page loads for the first time, I see this on the console:
Rendering the App component
App.js:12 false
Now, when I click the button, the console shows:
In clickHandler
App.js:16 false
App.js:8 Rendering the App component
App.js:12 true
If I click the button for the second time, the console prints:
In clickHandler
App.js:16 true
App.js:8 Rendering the App component
App.js:12 true
On the subsequent clicks, these lines get printed:
In clickHandler
App.js:16 true
My question: The state has been updated from false to true on the first click itself. So, why does the second click result in the component being re-rendered, even when the state is not changing?
Upvotes: 5
Views: 124
Reputation: 3994
From the Github issue, find this comment
This is a known quirk due to the implementation details of concurrency in React. We don't cheaply know which of two versions is currently committed. When this ambiguity happens we have to over render once and after that we know that both versions are the same and it doesn't matter.
So we cannot help the component in question BUT we can help the children from not getting affected.
How?
Use React.memo.
The component children would therefore not get affected by the second, useless re-render.
Upvotes: 2