React.js - How can I make setInterval know when a variable has changed its state/value?

47 Views Asked by At

Below is my relevant Javascript code -

  useEffect(()=> {
    Promise.all([
    faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
    faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
    faceapi.nets.faceRecognitionNet.loadFromUri("/models"),
    faceapi.nets.faceExpressionNet.loadFromUri('/models')
    ]).then(()=> {
      if(navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices
          .getUserMedia({ audio:false, video:true })
          .then((stream) => {
            console.log(stream)
            const video = document.getElementById("video");
            videoRef.current.srcObject = stream;
            console.log("video is " + video)
            video.play();
            setisLoaded(true);
            addEvent();
          })
          .catch((e) => {
            console.log(e);
          });
      }
    });
    }, []);

      const addEvent = () => {
        console.log("Inside")
        const video = document.getElementById("video");
        video.addEventListener("play", () => {
          const canvas = faceapi.createCanvas(video);
          canvas.id = "canvas";
          document.querySelector("#video").append(canvas);
          document.body.append(canvas);
          const displaySize = { width:width, height:height };
          faceapi.matchDimensions(canvas, displaySize);
          setInterval(async () => {
            const detections = await faceapi.detectAllFaces('video', new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions();
            const resizedDetections = faceapi.resizeResults(detections, displaySize);
            canvas
              .getContext("2d")
              .clearRect(0, 0, canvas.width, canvas.height);
            faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
            if(resizedDetections[0].expressions && tracking) {
              setData(arr => [...arr, resizedDetections[0].expressions]);
            }
          }, 100);
        })
      }

The if statement in the setInterval function always evaluates the tracking state variable as false. The tracking variable is initially set to false, but I later change the state to true (in a function that is not shown). However, the setInterval function still evaluates the tracking variable to be false.

Is there any way for me to ensure the setInterval function knows when a variable or state changes?

I tried using a localStorage variable and even the useRef react hook, but got the same result. I tried using the useInterval hook as well, but that did not work.

1

There are 1 best solutions below

0
dlitsman On

It would be helpful to see the full example as your useEffect is not full. I don't see dependencies. Are you sure that tracking is part of useEffect dependencies?

In general useEffect will not update values of variables that are not part of dependencies array. This is most likely the issue here.

It worth mentioning that adding tracking as part of dependencies list will cause you to reload models on change. So you will need to add extra checks or refactor this useEffect. You might also need to call video.removeEventListener for cleanup

Docs: https://react.dev/reference/react/useEffect