React useState unexpected extra render

Viewed 51

Taking this simple React counter example:

    const { useState } = React;
    
    function Example() {
      // Declare a new state variable, which we'll call "count"
      const [count, setCount] = useState(0);
    
      console.log("Example")
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(1)}>
            Click me
          </button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<Example />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

I've intentionally set the setCount handler to just const value for experimental reasons. And there is something very strange to me - the App re-renders the second time when I click the button the second time! (I'm getting Example output on the first and ALSO on the second click!)

My BIG question is HOW can it happen if in the case of the second click the value of the count variable HASN'T changed since the first click!? (by clicking the first time is set to just 1 and the second time ALSO to 1!)

When I click the third time and more it seems to work as expected - there are no further re-renders...

Can someone please explain me the reason of this extra render after the secon click?

P.S.

PLEASE don't tell me that the cause of this may be the react strict mode - As anyone can CLEARLY see I'm NOT using the strict mode anywhere!!!

2 Answers

Ref : https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update

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.

try this---

In place of setCount(1) make it setCount(count++) or setCount(count+1) Now it will work . Beacuse you are just setting value of count as 1 on every click.

Related