【问题标题】:React Hook useRef is null when used with useEffect与 useEffect 一起使用时,React Hook useRef 为 null
【发布时间】:2020-05-27 17:22:53
【问题描述】:

我想使用 React Hook 的 useRef 设置视频流的 src 对象,但视频引用为空,我收到错误:TypeError: Cannot set property 'srcObject' of null at getMedia。我正在使用useEffect 调用记录参考的函数。

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

我已阅读 useRef 上的文档,并查看了 Stack Overflow 和 Github 上的所有其他帖子,但无法弄清楚这一点。最近的帖子是this one。我做错了什么?

精简代码:

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

【问题讨论】:

  • Chrome 控制台的问题是它不能反映你登录时对象的状态;当控制台 UI 评估您将看到输出的对象时。因此,您在 ref 为 null 时登录,但当 UI 在 Chrome 中更新时,它已被填充。

标签: javascript reactjs react-hooks webcam getusermedia


【解决方案1】:

根据您提供的代码,对我来说似乎工作正常。

为了播放视频,我在效果中添加了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

【讨论】:

  • 您对条件渲染的评论让我意识到这是问题的原因。请参阅我使用完整代码更新了沙箱:codesandbox.io/s/blissful-goldstine-rp9k5
  • @JAM,希望这会有所帮助!只需确保仅当相应元素实际位于 DOM 中时才使用元素引用。否则它将为空。
  • 非常感谢!我不知道你可以有多个 useEffects
  • 这实际上是钩子最好的部分之一!如果逻辑复杂或者您想在多个地方使用相同的逻辑,您可以使用任意数量并将它们抽象为自定义逻辑
猜你喜欢
  • 2020-11-19
  • 2019-10-08
  • 2021-12-31
  • 2020-02-17
  • 1970-01-01
  • 2022-11-23
  • 2021-01-16
  • 2021-04-14
  • 2023-03-20
相关资源
最近更新 更多