1

I can't understand why React render 3 times in this example:

const {useEffect, useState} = React;

const App = () => {

  const [timer, setTimer] = useState(0);

  const addTimer = () => {
    console.log('timer', timer);
    setTimer(timer + 1);
  }

  useEffect(() => {
    console.log('Use effect');
  
    setInterval(addTimer, 8000);
  }, [])


  return <h5>Time: {console.log('Render') || timer}</h5>;
};

ReactDOM.render(<App />, document.getElementById('root'));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>

Output of console:

Render
Use effect
timer 0
Render
timer 0
Render
timer 0 (infinity)

The first render is initial and we see in console Render. Then after initialization useEffect starts and we see Use effect in console and we initialize timer every 8 seconds. I clearly understand that in addTimer function timer variable always will be 0. After 8 seconds we update state from 0 to 1, so we can see timer 0 and after Render because now we have new state. If I'm right then in new state timer is 1 but when addTimer starts second time we again update state to 1 but previous state already is 1, so we didn't update anything but we can see Render third time after timer 0. After this we will see only timer 0 infinity times because we don't update state we always put 1 as a new state so there is no need in render again

Please explain me why in console I see third Render?

P.S. I know how to properly update state and I understand that in addTimer function timer variable always will be 0. Please don't explain me this parts

P.S.S. It doesn't matter on React version here is examples

Version 16.8.0

const {useEffect, useState} = React;

const App = () => {

  const [timer, setTimer] = useState(0);

  const addTimer = () => {
    console.log('timer', timer);
    setTimer(timer + 1);
  }

  useEffect(() => {
    console.log('Use effect');
  
    setInterval(addTimer, 8000);
  }, [])


  return <h5>Time: {console.log('Render') || timer}</h5>;
};

ReactDOM.render(<App />, document.getElementById('root'));
<div id="root"></div>

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

Version 17.0.0

const {useEffect, useState} = React;

const App = () => {

  const [timer, setTimer] = useState(0);

  const addTimer = () => {
    console.log('timer', timer);
    setTimer(timer + 1);
  }

  useEffect(() => {
    console.log('Use effect');
  
    setInterval(addTimer, 8000);
  }, [])


  return <h5>Time: {console.log('Render') || timer}</h5>;
};

ReactDOM.render(<App />, document.getElementById('root'));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
EzioMercer
  • 1,502
  • 2
  • 7
  • 23
  • @EstusFlask I clearly understand why in my example `timer` in `addTimer` function is always 0. I can't understand why React render 3 times instead of 2? – EzioMercer Jul 19 '22 at 07:57
  • I guess the example is misleading then, could be `setTimer(1)`. I see what you mean. Likely some kind of reconciliation happens, but I'm unaware of that. Interesting thing but shouldn't be a real issue because nothing should rely on render calls count, – Estus Flask Jul 19 '22 at 10:15
  • @yousoumar It doesn't matter. I tried on versions `16.8.0`, `17.0.0` and `18.1.0`. You can copy and run my example and experiment with other versions. And I don't see that `useEffect` run several times, because I see only one message `Use effect` in console – EzioMercer Jul 19 '22 at 10:50
  • I see @EzioMercer. Deleted the suggestion. – Youssouf Oumar Jul 19 '22 at 10:55
  • Yes both of you are right. It is not the real issue. I just want to understand why we have external rendering when state doesn't change second time? – EzioMercer Jul 19 '22 at 10:57
  • Answered by the man himself here: [React component sometimes renders twice with unchanged state](https://stackoverflow.com/questions/60883745/react-component-sometimes-renders-twice-with-unchanged-state) – Ed_ Jul 19 '22 at 11:18
  • @Ed_ Thank you! This isn't an answer as to why this is happening, but it means it's not my fault and React can re-render even though the state doesn't change :) – EzioMercer Jul 19 '22 at 11:34

0 Answers0