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>