【问题标题】:Getting a TypeError using the useRef hook..."null is not an object"使用 useRef 钩子获取 TypeError...“null 不是对象”
【发布时间】:2021-11-02 14:48:12
【问题描述】:

React 开发者您好。

所以我正在为客户编写一个应用程序。客户想要一个在视口中显示视频时播放视频(无声音,内联播放)的页面,并在视频超出视口时暂停。所以我做了一个自定义钩子来做到这一点。这是我的代码(忽略导入,只是 useRef 和 useEffect):

const usePlayVideo = options => {
const wrapperRef = useRef(null);
const videoRef = useRef(null);
const handleVid = entries => {
    const [entry] = entries;
    if (entry.isIntersecting) videoRef.current.play();
    else videoRef.current.pause();
    };
useEffect(() => {
    const wrapper = wrapperRef.current;
    const observer = new IntersectionObserver(handleVid, options);
    if (wrapper) observer.observe(wrapper);
    return () => {
        if (wrapper) observer.unobserve(wrapper);
    };
    }, [wrapperRef, options]);
    return [wrapperRef, videoRef];
};
export { usePlayVideo };

然后,在组件中,我导入钩子并像这样使用它:

function ClientAsk() {
    const [wrapperRef, videoRef] = usePlayVideo({
        root: null,
        rootMargin: "0px",
        threshold: 0.3,
    })

    return (
        {/* bunch of other divs and stuff */}
        <div className="grid_s_start_3 grid_s_span_20" ref={wrapperRef}>
            <video ref={videoRef} id="video" playsInline muted preload="auto" loop style={{ width: "100%" }}>
                <source src={ClientVid} type="video/mp4" />
            </video>
        </div>
        {/* rest of other divs and stuff */}
        );
}

export default ClientAsk;

就是这样。

在我的开发环境的浏览器中,这很好用!按预期工作!我很兴奋。

但我在我的 iPhone 上使用 iOS Safari 进行了尝试,它也可以工作...直到我在播放视频时返回上一页。

所以,页面顶部有一个“

但是,如果我停止滚动视频,并且它正在播放,并且我按下后退按钮(或 Safari 浏览器的后退按钮),我会收到一个开发错误:

TypeError: null is not an object (evaluating 'videoRef.current.pause')
handleVid
src/hooks/usePlayVideo.js:8
5 | const videoRef = useRef(null);
6 | const handleVid = entries => {
7 | const [entry] = entries;
> 8 | if (entry.isIntersecting) videoRef.current.play();
| ^ 9 | else videoRef.current.pause();
10 | };

现在,我想我知道为什么会发生这种情况......但是,我根本无法弄清楚如何解决这个问题或让错误停止发生。我想知道是否有人对此有任何提示?我在自定义钩子中使用了错误的钩子吗?我不应该使用“null”作为 useRef 的默认值吗?这只是一个 iOS 问题吗?

任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 尝试改变这一行:videoRef.current.play();videoRef &amp;&amp; videoRef.current.play(); --- 还有:else videoRef && videoRef.current.pause();
  • @SajibKhan 我刚试过。不幸的是,它没有修复它。移动 iOS Safari 上的相同类型错误。 (在桌面上运行良好。)感谢您的回复!
  • VideoRef 总是真实的,它的current 值可能是假的(在这种情况下为空),你可以用if (videoRef.current) { } 包装你的useEffect 逻辑或handleVid 逻辑
  • @Zac 澄清您的评论,您是说我应该用if (videoRef.current) 替换if (entry.isisIntersecting) 吗?或将 videoRef.current 添加到当前条件?感谢您的回复!
  • 它与entry.isisIntersecting 条件无关,问题是在这种情况下你的代码是用videoRef.current = null 执行的,在你当前的条件下,你要么调用.play().pause() 两者都会产生相同的错误,因此您可以将这三行包含在handleVid 函数中,条件为if (videoRef.current) { }

标签: javascript reactjs react-hooks null typeerror


【解决方案1】:

所以问题是这行代码返回了一个null值导致返回上一页时出错:

const handleVid = entries => {
    const [entry] = entries;
    if (entry.isIntersecting) videoRef.current.play();
    else videoRef.current.pause();
};

根据上述@Zac,其原因是因为 videoRef 常量在写入时始终为真值,其当前值可能为假(在这种情况下为 null)。

所以,我按照他的建议重写了它,如下所示,将 handleVid 函数包装在 if (videoRef.current) 条件中:

if (videoRef.current) { 
   if (entry.isIntersecting) videoRef.current.play(); 
 else videoRef.current.pause(); 
 }; 

这解决了 Safari 上的 TypeError,并且在返回上一页时不再显示。

非常感谢您的帮助!

【讨论】:

  • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
  • 我已经重写了我的答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-05-08
  • 2021-04-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
相关资源
最近更新 更多