Home > Software design >  Why is this code render 0,2,3,0,1,2,3 etc
Why is this code render 0,2,3,0,1,2,3 etc

Time:01-20

   const [index, setIndex] = useState(0);
   useEffect(()=>{
     if (index === 3){
         setIndex(0)
         console.log(index)
     }else{
       setTimeout(() => setIndex((index) => index   1), 2000);
       console.log(index)
       
     }
     }, [index]);

So my question is why is this code above skips 1 the first time? The console.log() gives back the following 0 0 2 3 0 1 2 3 0 now here I understand the 0 0 cause I logging it out then the 2 for some reason I don't get it and again 3 0 1 2 is understandable

I want to change the name in the DOM according the index of it in an array

CodePudding user response:

In developement mode the useEffect will run twice on mount because of StrictMode.

So the setTimeout will run twice and since you're not providing a cleanup function it will live on and keep setting the state. Which results in setting the state twice and so going from 0 to 2.

In production StrictMode is disabled and thus will not fire the useEffect twice.

Instead you could do something like this

useEffect(() => {
  let timeoutId;
  if (index === 3) {
    setIndex(0);
    console.log(index);
  } else {
    timeoutId = setTimeout(() => setIndex((index) => index   1), 2000);
    console.log(index);
  }
  return () => clearTimeout(timeoutId);
}, [index]);

However if you're trying to make some sort of counter/interval I recommend using setInterval.

useEffect(() => {
  // set id to use in the cleanup
  const timerId = setInterval(
    () =>
      // use inline check so we have access to the actual index
      setIndex((prevIndex) => {
        if (prevIndex === 3) return 0;
        return prevIndex   1;
      }),
    2000
  );

  return () => clearInterval(timerId);
}, []);
  • Related