Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJs : useRef current getting null

I am trying to turnoff camera and flashlight when the component gets unmount , I am using react hook I have two function startCamera() and stopCamera() , I am calling startcamera when the component gets mount and stop camera when component gets unmount. But its showing me error when stopCamera is called while unmounting enter image description here

i have created an another button to test if StopCamera() working and i found its working , but i want to call the function when component is getting unmounted

my code:

CameraScreen.js


import "./styles.css";
import { useState, useEffect, useRef } from "react";

export default function CameraScreen() {
  const videoElement = useRef(null);
  const [facingMode, setFacingMode] = useState("environment");
  const handleFacingModeToggle = () => {
    stopCamera();
    facingMode === "environment"
      ? setFacingMode("user")
      : setFacingMode("environment");
  };
  useEffect(() => {
    // const getUserMedia = async () => {
    //   try {
    //     const stream = await navigator.mediaDevices.getUserMedia({
    //       video: true
    //     });
    //     videoElement.current.srcObject = stream;
    //   } catch (err) {
    //     console.log(err);
    //   }
    // };
    // getUserMedia();
    startCamera();
    return function cleanup() {
      stopCamera();
    };
  }, []);

  const stopCamera = () =>
    videoElement.current.srcObject &&
    videoElement.current.srcObject.getTracks().forEach((t) => t.stop());
  function startCamera() {
    if (navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices
        .getUserMedia({
          video: { facingMode: facingMode },
          width: { ideal: 1280 },
          height: { ideal: 720 }
        })
        .then(function (stream) {
          if (videoElement.current) videoElement.current.srcObject = stream;
          const track = stream.getVideoTracks()[0];

          //Create image capture object and get camera capabilities
          const imageCapture = new ImageCapture(track);
          const photoCapabilities = imageCapture
            .getPhotoCapabilities()
            .then(() => {
              //todo: check if camera has a torch

              //let there be light!

              track.applyConstraints({
                advanced: [{ torch: true }]
              });
            });
        })
        .catch(function (error) {
          alert("Please check your device permissions");
          console.log("Something went wrong!");
          console.log(error);
        });
      if (videoElement.current)
        videoElement.current.onloadeddata = function () {
          if (window.NativeDevice)
            window.NativeDevice.htmlCameraReadyToRecord(true);
        };
    }
  }
  return (
    <>
      <video
        autoPlay={true}
        ref={videoElement}
        style={{
          minHeight: "67.82vh",
          maxHeight: "67.82vh",
          maxWidth: "100%",
          minWidth: "100%"
        }}
        className="border-3rem bg-[#666]"
      ></video>

      <button onClick={stopCamera}> stopCamera</button>
    </>
  );
}

App.js

import "./styles.css";
import { useState } from "react";
import CameraScreen from "./cameraScreen";
export default function App() {
  const [switchS, setSwitchS] = useState(false);
  return (
    <div>
      <button className="" onClick={() => setSwitchS(!switchS)} value="switch">
        switch
      </button>
      
      {switchS && <CameraScreen />}
      {!switchS && "Blank Screen"}
    </div>
  );
}

PS: the above code working at :https://5t2to.csb.app/

codesandbox link : https://codesandbox.io/s/practical-fast-5t2to?file=/src/cameraScreen.js

like image 538
TINTIN Avatar asked Oct 15 '25 15:10

TINTIN


1 Answers

You can use useLayoutEffect hook. It works just before unmounting, like componentWillUnmount.

Here is an example to that https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/random.js

You can go to https://ikqdn.csb.app/rand in sandbox browser and check the console on clicking to home button.

You can see the difference in working while unmounting of both useEffect and useLayoutEffect


It preserves ref.current, so what you can do is, you can pass ref.current in the function that you are calling just before unmounting, to prevent ref to the dom elment.

like image 189
Himanshu Singh Avatar answered Oct 17 '25 17:10

Himanshu Singh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!