当对象不在 DOM 中时,如何解决无法在 React 挂钩中读取 null 的 querySelector

How to fix cannot read querySelector of null in React hook when Object is not in DOM

components/VideoPlayer.js

import '../../style/VideoPlayer/VideoPlayer.css';
const VideoPlayer = () => {...some code...return(...some code...)} export default VideoPlayer

VideoContainer.js

import VideoPlayer from "../../VideoPlayer"
import useVideoPlayer from "../../../hooks/useVideoPlayer"

const VideoContainer = ({ info }) => {

const { playPause, toggleFullScreen, fullscreen } = useVideoPlayer()
return (
<React.Fragment>
<div>
...
{/* {playPause == true ? (
            <div><VideoPlayer/></div>)
            : null} */}

{fullscreen && <div id="testing"><VideoPlayer src={info.somesrc} title={info.sometitle} /></div>}

{/* <div id="testing"><VideoPlayer src={info.somesrc} title={info.sometitle} /></div> */}
...
</div>
</React.Fragment>
)
import React, { useState, useEffect, useRef, useLayoutEffect } from 'react'
const useVideoPlayer = () => {
    const [playVideo, setPlayVideo] = useState(false)
    const [fullscreen, setFullscreen] = useState(false)

    useEffect(() => {
    const controlsContainer = document.querySelector('.video-container .controls-container');
    const playPauseButton = document.querySelector('.video-container .controls button.play-pause');
    const pauseButton = playPauseButton.querySelector('.paused'); // typeError cannot read property querySelector of null
    ...some other queryselectors...
    }, []);

const displayControls = () => {
    let controlsTimeout;
    const controlsContainer = document.querySelector('.video-container .controls-container');
    ...
}

const playPause= () => {
  const video = document.querySelector('.video-container video');
  if (...) {
    video.play(); 
    setPlayVideo(true);
  } else (...) {
    video.pause();
    setPlayVideo(false);
  };
}

const toggleFullScreen = () => {
 const videoContainer = document.querySelector('.video-container');
 if (...) {setFullscreen(true)} else (...) {setFullscreen(false)};
}

...
document.addEventListener('fullscreenchange', () => {
...
}

const video = document.querySelector('.video-container video');

video && (video.addEventListener('timeupdate', () => {
...
}

...a dozen other addEventListeners for different elements fetched by querySelectors...

return { playPause, toggleFullScreen, fullscreen }

}

export default useVideoPlayer;

我正在将 playPausetoggleFullscreen 函数和 fullscreen reactcontext 从 useVideoPlayer 挂钩传回反应容器。
我使用 && 并检查 fullscreen 是真还是假以呈现 <VideoPlayer/> 或不

当组件不在 DOM 中时,useVideoPlayer 挂钩不起作用,我该如何解决?

Uncaught TypeError: Cannot read property 'querySelector' of null
    at eval (useVideoPlayer.js:41)
    at commitHookEffectListMount (react-dom.development.js:19731)
    at commitPassiveHookEffects (react-dom.development.js:19769)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at flushPassiveEffectsImpl (react-dom.development.js:22853)
    at unstable_runWithPriority (scheduler.development.js:653)
    at runWithPriority (react-dom.development.js:11039)
    at flushPassiveEffects (react-dom.development.js:22820)

我试过 useLayoutEffect,通过 useRef(null) 并包装在 if (containerRef.current) {} 中,但没有区别

您需要在尝试使用之前检查该元素是否存在:

const pauseButton = playPauseButton && playPauseButton.querySelector('.paused'); 

如果您想要更具可扩展性的东西,您可以在 VideoContainer 中显式控制它是否呈现,然后将其传递给您的挂钩:

const VideoContainer = ({ info }) => {
    const [mounted, setMounted] = useState(false)
    const { playPause, toggleFullScreen, fullscreen } = useVideoPlayer(mounted)
    return (
    ...
    {mounted ? <VideoPlayer/> : null}