Giorgos
Giorgos

Reputation: 65

React useState reruns the component function on no change

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

Answers (2)

Drew Reese
Drew Reese

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

Mai Truong
Mai Truong

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

Related Questions