React useState unexpected extra render

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);

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 second 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!!!

Its an odd one isn’t it?

If you change button onClick to

<button onClick={() => setCount(0)}>

You would then expect to see ‘Example’ logged twice, but it only logs once.

There is a similar question on stackoverflow, but for me it doesn’t answer the question satisfactorily.

Maybe someone here can clarify? I will need to do a bit of digging on this one.

Just to try and see a pattern I am trying the following.

const { useState } = React;

let index = 0;
const sequence = [0,0,1,1,1,0,0,0]

export const App = () => {
  const [count, setCount] = useState(0);

  console.log('rendered')

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {
        console.log(`index ${index} - value is ${sequence[index] || 0}`)
        setCount(sequence[index++] || 0)
      }}>
        Click me
      </button>
    </div>
  );
}

Output

rendered
index 0 - value is 0
index 1 - value is 0
index 2 - value is 1
rendered
index 3 - value is 1
rendered // (not committed to DOM)
index 4 - value is 1
index 5 - value is 0
rendered
index 6 - value is 0
rendered // (not committed to DOM)
index 7 - value is 0
index 8 - value is 0
index 9 - value is 0
...

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.