Reputation: 230
if i used setInterval(line 15) without useEffect than it gives result 2^n-1(0,1,3,7,15,31,63...) instead of(0,1,2,3,4,..) . so i have some question
1)why i am getting that output when I directly called setInterval without useeffect 2)is there any way if I change setCount(line 9) and its gives correct output by use setInterval directly without useEffect(as I did)
3) if the use of setInterval is not possible without useEffcet than why it is not possible?
if i put setInterval in useEffect and render initially once( line 12,13,14) than it gives correct output.....
but I do not get the correct output when I use directly setInterval. what is diff bet them?
in both cases, I call setInterval once but the output is diff.
import React, {useEffect, useState } from 'react'
export default function IncorrectDependency() {
const [count,setCount]=useState(0)
const inc=()=>{
// console.log(count)
setCount(preVal=>preVal+1)
// setCount(count+1)
}
// useEffect(()=>{
// setInterval(inc,1000)},[]
// )
setInterval(inc,1000)
return (
<div>
<h1>{count}</h1>
</div>
)
}
Upvotes: 0
Views: 2792
Reputation: 11
Dan Abramov explains why this isn't a good idea:
"it’s not the idiomatic way to do it. eg it won’t work correctly if you have multiple instances of the same component. it breaks the rules — it does a side effect (setInterval) during rendering, which the page said you should not do :) once you break the rules, all bets are off"
https://twitter.com/dan_abramov/status/1577395235340095501?s=20&t=nNnYyjLvHs5by_dqF5l8zg
Upvotes: -1
Reputation: 21901
When we do a set state, functional components will re-execute from top to bottom, how ever when we use useState, useCallbacks etc.. they will not re-initialize as variables, functions,
So in this case, setInterval
will re-initialize on each and every setCount
, because of the state got changed,
step by step
setInterval
again and it will trigger it, so now we have two setIntervals
You can achieve the expected result without useEffect
by clearing the previous interval on each re-render which is happen due to setCount
create a variable to hold the set interval, code
const interval = null;
//this should be declare out side the component,
//because if we declare it inside the component it will redeclare,
//and the reference to the previous setInterval will be lost in that case no-way to clear the setInterval.
export default function IncorrectDependency() {
....
if (interval) {
clearInterval(interval);
}
interval = setInterval(inc, 1000);
....
}
alternatively react has a hook which can hold the same variables without re-initializing on each renderings, check it out useRef
here is a code-demo
const intvl = useRef(null);
....
if (intvl?.current) {
clearInterval(intvl.current);
}
intvl.current = setInterval(inc, 1000);
.....
Upvotes: 7
Reputation: 280
when you directly use setInterval what is happening as this is a function it will be called on state change so again a setInterval will be triggered and so on which actually give you the incorrect result, so you shouldn't use setInterval without use effect, also on unmount you should clearthe interval
Upvotes: 1