Shariq Hasan Khan
Shariq Hasan Khan

Reputation: 530

Why is the componet being re-rendered twice?

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

Answers (1)

Aakash Verma
Aakash Verma

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

Related Questions