clearInterval not clearing the set interval onMouseUp

153 Views Asked by At

Trying to make a button event onMouseDown, a function should run at the end of the set amount of time. The function runs onMouseDown and clears the interval onMouseUp, but the interval still runs after releasing the button.

This is the code currently. I have the interval global and set it in the planting function. It should unset in the notPlanting function, but it does not.

import React from "react";

function PlantDefuser() {
    var interval

    function planting() {
        interval = setInterval(() => {
            console.log("Defuser Planted")
        }, 1000)
    }

    function notPlanting() {
        console.log(interval)
        clearInterval(interval)
    }

    return (
        <button onMouseDown={planting} onMouseUp={notPlanting}>Press and Hold</button>
    )
}

export default PlantDefuser
3

There are 3 best solutions below

1
Martinez On BEST ANSWER

This could help you:

useRef allows us to store and update data in the component without triggering a re-render. Now the only re-render happens when the props are updated.

We can store interval in a ref like so

import { useRef } from "react";

const PlantDefuser = () => {
  const interval = useRef();

  function planting() {
    interval.current = setInterval(() => {
      console.log("Defuser Planted");
    }, 1000);
  }

  function notPlanting() {
    clearInterval(interval.current);
  }

  return (
    <button onMouseDown={planting} onMouseUp={notPlanting}>
      Press and Hold
    </button>
  );
}

export default PlantDefuser
2
Angel Zlatanov On

When you declare variables like so in the function component, it is being created on each render. You should be saving the interval id in a state like so:

import React, { useState } from "react";

const PlantDefuser = () => {
    const [plantingInterval, setPlantingInterval] = useState(null);

    const planting = () => {
        const plantingIntervalId = setInterval(() => {
            console.log("Defuser Planted");
        }, 1000);
        setPlantingInterval(plantingIntervalId);
    };

    const notPlanting = () => {
        clearInterval(plantingInterval);
        setPlantingInterval(null);
    };

    return (
        <button onMouseDown={planting} onMouseUp={notPlanting}>
            Press and Hold
        </button>
    );
};

export default PlantDefuser;

You might also want to make sure the interval is being cleared when the component unmounts.

0
monim On

You can use useEffect hook with cleanup function to manage the clearInterval method .

like this :

function PlantDefuser() {
  const [run, setRun] = useState(false);

  useEffect(() => {
    if (run) {
      const countTimer = setInterval(() => {
        console.log("Defuser Planted");
      }, 1000);

      return () => {
        console.log(countTimer);
        clearInterval(countTimer);
      };
    }
  }, [run]);

  return (
    <button onMouseDown={() => setRun(!run)} onMouseUp={() => setRun(!run)}>
      Press and Hold
    </button>
  );
}

export default PlantDefuser;