与 useEffect 一起使用时,React Hook useRef 为 null

React Hook useRef is null when used with useEffect

我想使用 React Hook 的 useRef 设置视频流的 src 对象,但视频引用为空,我收到错误:TypeError: 无法设置 属性 'srcObject' 在 getMedia 处为空。我正在使用 useEffect 来调用记录 ref 的函数。

奇怪的是我同时看到了 null 和电流值。查看控制台日志的屏幕截图:

我已阅读 useRef and looked at every other post on Stack Overflow and Github but cannot figure this out. The closest post is 上的文档。我做错了什么?

压缩代码:

const App = () => {
  const webcamRef = useRef(null)

  useEffect(() => {
    getMedia();
  }, [webcamRef])

  const getMedia = async () => {
    try {
      console.log(webcamRef);
      let stream = await navigator.mediaDevices.getUserMedia({ video: true });
      webcamRef.current.srcObject = stream;
    } catch (err) {
      console.error(err);
    }
  };

  return <video id='webcam' ref={webcamRef} />
}

完整代码: 沙盒:https://codesandbox.io/s/blissful-goldstine-rp9k5

根据您提供的代码,我这边似乎工作正常。

为了让视频播放,我添加了 webcamRef.current.play() 效果。

useEffect 应始终 运行 在组件完全安装(/渲染)后,因此当效果 运行 时 webcamRef.current 不应为空,除非有条件地渲染视频。

另外,在 useEffect 中,你不应该在依赖数组中有一个 ref,因为它什么都不做,并且看起来效果会在 ref 改变时被重新触发,即使它不会。

https://codesandbox.io/s/inspiring-sara-9skhr?file=/src/App.js


来自 JAM 关于有条件地呈现视频的更新:

您要做的主要事情是分离出效果。您希望 getMedia 调用仅在视频元素位于页面上时 发生,否则 webcamRef.current 无法指向任何内容。

因此,在这种情况下,我将第一个效果集加载为 true,然后我制作了第二个效果,使用 loaded 作为依赖项,以便在预处理完成后调用 getMedia。

  useEffect(() => {
    const loadItems = async () => {
      console.log("preprocessing here");
    };  
    loadItems().then(() => {
      setLoadedStatus(true);
    });
  }, []);

  useEffect(() => {
    if (!loaded) return;
    const getMedia = async () => {
      try {
        console.log(webcamRef.current);
        let stream = await navigator.mediaDevices.getUserMedia({ video: true });
        webcamRef.current.srcObject = stream;
        webcamRef.current.play();
      } catch (err) {
        console.error(err);
      }
    };

    getMedia();
  }, [loaded]);

https://codesandbox.io/s/distracted-violet-s92d0?file=/src/App.js