I know this code will work and the count
value will be updated after every 2 seconds:
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
setInterval(() => {
setCount(prev => prev 1);
}, 2000);
}, []);
return <h1>{count}</h1>;
}
I am trying to understand why the below code doesn't work:
React.useEffect(() => {
const interval = setInterval(() => {
setCount(count 1);
console.log('hello');
}, 2000);
return () => clearInterval(interval);
}, []);
In this case, count
stays at 1 but the setInterval
is called after every 2 seconds because hello is being logged every 2 seconds.
How
setInterval
is being called when component is not being rendered? Does it operate outside of React lifecycle or something?When I pass callback to
setCount(prev => prev 1)
, then it works fine? Why? How theprev
in callback getting the updated value?
I have read similar answers but still it is not making sense to me so if someone could please clear the doubt.
Thanks
CodePudding user response:
How setInterval is being called when component is not being rendered? Does it operate outside of React lifecycle or something?
Yes, setInterval is a function that's part of the core javascript language. By calling setInterval, you ask the browser to call the specified function every 2000ms. React is not involved in this.
When I pass callback to setCount(prev => prev 1), then it works fine? Why? How the prev in callback getting the updated value?
The useState
hook is designed to allow this interaction. React promises that if you pass a function into setCount
, then react will call your function and pass in the latest value.
The exact code with which they implement this can be tricky to step through since they reuse a lot of general purpose functions to implement several different hooks, but if you want to poke around their codebase you can look here: https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.new.js#L1525
CodePudding user response:
When you create the interval function, count
will be the value at the moment of creation (so 0).
When it gets called later, it will still hold that value, since it won't get changed in that context. So it will always set it to 0 1, so 1.
When you pass a callback function, it will use the current, correct value.
Hope this could clear things up!
CodePudding user response:
This version: setCount(prev => prev 1)
uses the previous state value every-time the interval gets run.
This version: setCount(count 1)
uses count
when the useEffect
was las run (in this case 0, so 0 1). Because there is an empty dependency array this hook is only run once.
If count was included in the dependency array of useEffect
then it would get re-run when the value of count
changes.
Running this may help to see what's going on:
React.useEffect(() => {
console.log('running useEffect')
const interval = setInterval(() => {
setCount(count 1);
console.log('hello ', count);
}, 500);
return () => {
console.log('clear interval')
clearInterval(interval);
}
}, [count]);