javascriptreactjselectronsettimeoutcleartimeout

Cannot stop recursive setTimeout function in my react electron screen tracker app


I am working on a screen tracker app which takes screen screenshots every 10 minutes and upload it to a firebase storage. I'm calling the start function when clicking on the start function and want it to stop capturing screen when I click on the stop button, but it's not working and I can't understand why. I am a self taught developer with less than 3 months of experience. Please help.

function App() {
  // store the screenshots in an array
  const [newScreenshots, setNewScreenshots] = useState("");
  // const [screenshots, setScreenshots] = useState([]);
  const [timeoutId, setTimeoutId] = useState(false);
  const [progress, setProgress] = useState(0);

  const uploadFiles = (img) => {
    // logic
    const storageRef = ref(storage, `/screenshots/${uuidv4()}`);

    uploadString(storageRef, img, "data_url").then((snapshot) => {
      console.log("Uploaded a data_url string!");
    });
  };

  let newTimeoutId;
  const screenshot = async () => {
    setTimeoutId(true);

    const newTimeoutId = setTimeout(async () => {
      const screenshotData = await ipcRenderer.invoke("capture");
      const string = new Buffer.from(screenshotData).toString("base64");
      const img = `data:image/png;base64,${string}`;
      console.log(img);
      uploadFiles(img);
      screenshot();
    }, 600000);
  };

// This function is not working. I'm trying to call it using  button click.

  const stopScreenshot = () => {
    setTimeoutId(false);
    clearTimeout(newTimeoutId);
  };

Solution

  • So, I'd avoid using setTimeout and instead use setInterval that takes a function and an interval of time to fire it. Additionally I would create a function takeScreenshot, that just takes care of taking the screenshot(maybe you'll want to take a screenshot on demand someday, having half of the job done would be nice :))

    const takeScreenshot = async () => {
    const screenshotData = await ipcRenderer.invoke("capture");
          const string = new Buffer.from(screenshotData).toString("base64");
          const img = `data:image/png;base64,${string}`;
    
          uploadFiles(img);
          screenshot();
    }
    
    const startRecording = () => {
          setInterval(() => takeScreenshot() , 60000)
    }
    
    stopRecording = () => {clearInterval(startRecording)}
    

    **you might need to edit it a bit