Home > Software engineering >  ClearInterval is not working as expected with useRef in React
ClearInterval is not working as expected with useRef in React

Time:08-16

I have created one setInterval which is being called on App Load, Like this

  let abc = true;
  let def = true;
  const intervalRef = useRef(null);

  if (abc) {
    intervalRef.current = setInterval(() => {
      console.log("hello console", def);
    }, 2000);
    abc = false;
  }

And trying to stop this interval using clearInterval on some click handler like this -

const clear = () => {
    clearTimeout(intervalRef.current);
    def = false;
    console.log(def);
  };

Issues I am facing right now are -

  1. Why SetInterval is not stopped on click handler, while I am already cleared it in function?
  2. Why value of def in not getting updated in setInterval.

Edit pedantic-hypatia-uvuonk

CodePudding user response:

this is not a silly question, it's something I have seen many people struggling with. Let me clarify this:

  1. Why SetInterval is not stopped on the click handler, while I am already cleared it in function?

This is happening because your component is rendering more than once (so you are creating multiple intervals and only clearing the last one.

  1. Why the value of def is not getting updated in setInterval.

There are 2 things to consider here, first, the setInterval callback is not included in react lifecycle so the value does not get updated. Last, since you are only changing the value of a variable (but not the component state) the component will not be re-rendered and the code will remain the same.

You can find a very good article to deal with intervals in react here -> https://overreacted.io/making-setinterval-declarative-with-react-hooks/

I also leave you the code here as well as a code snippet link:

import "./styles.css";
import { useEffect, useRef, useState } from "react";
export default function App() {
  const [runInterval, setRunInterval] = useState(true);
  const [counter, setCounter] = useState(0);
  const intervalRef = useRef(null);

  useEffect(() => {
    if (runInterval) {
      intervalRef.current = setInterval(() => {
        setCounter((c) => c   1);
      }, 1000);
    }

    return () => {
      clearInterval(intervalRef.current);
    }; // clear interval when unmounting the component
  }, [runInterval]);

  const clear = () => {
    setRunInterval(false);
  };

  return (
    <div className="App">
      <h1 onClick={() => clear()}>Click me to Stop Interval</h1>
      <h2>{counter}</h2>
    </div>
  );
}

https://codesandbox.io/s/stoic-elbakyan-u5ezc3?file=/src/App.js:0-734

  • Related