setInterval() keeps running even after clearing it using clearInterval()

Most of the answers I found here was to use clearInterval() inside a return statement in a useEffect(). But, still for some reasons it keeps executing.

I'm also getting the following warning in the logs :-

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in StartTest (at SceneView.tsx:126)

attaching the code for Reference.

const [connectionInterval, setConnectionInterval] = useState(null);
const [batteryInterval, setBatteryInterval] = useState(null);
const [heartRateInterval, setHeartRateInterval] = useState(null);

useEffect(() => {
    startServices();
    return () => {
      clearServices();
    };
}, []);


const startServices= () => {
    let ctnInt = setInterval(() => checkConnection(), 5000);
    setConnectionInterval(ctnInt);
    let btryInt = setInterval(
      () =>
        Battery(value => {
          setBattery(value);
        }),
      900000,
    );
    setBatteryInterval(btryInt);
    let hrRtInt = setInterval(
      () =>
        HeartRate(
          hr => {
            if (finish) {
              clearInterval(heartRateInterval);
            }
            let rate = Math.round(hr);
            setHeartRate(rate);
          },
          onError => {
            console.log('API ERROR');
          },
        ),
      3000,
    );
    setHeartRateInterval(hrRtInt);
  };


  const clearServices = () => {
    clearInterval(connectionInterval);
    clearInterval(batteryInterval);
    clearInterval(heartRateInterval);
  };```

Solution 1:

You're not passing any deps to useEffect, so the effect functions never update, and in the version of clearServices that you call, connectionInterval and friends are all still null. See the note here.

In general I would approach setInterval like this:

useEffect(() => {
    const intervalFn = () => {
        console.log('interval fired')
    }
    const intervalId = setInterval(intervalFn, 1000)
    return () => {
        clearInterval(intervalId)
    }
}, [])

(this version really has no deps, because everything is captured inside useEffect. but in practice you would probably have some.)