为什么 React 悬停时播放或暂停出错

Why there is Error in Playing or Pausing When Hovered in React

我有几个视频要在我的应用程序中显示。 我想要它,如果它悬停它会播放,当鼠标离开它时,它会暂停。但是我的问题是它输出错误 Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

下面是我的代码

const Video = ({ video }) => {
  const videoRef = useRef();
  return (
    <div
      onMouseOver={() => video?.promoVideoUrl && videoRef?.current?.play()}
      onFocus={() => video?.promoVideoUrl && videoRef?.current?.play()}
      onMouseOut={() => video?.promoVideoUrl && videoRef?.current?.pause()}
      onBlur={() => video?.promoVideoUrl && videoRef?.current?.pause()}
      className="col-12"
    >
      <>
        <a target="_blank" href={`/videos/${video.id}`} rel="noreferrer">
          <video
            ref={videoRef}
            muted
            height="100%"
            width="100%"
            poster={video?.poster}
            src={video?.url}
            loop
            preload="auto"
          />
        </a>
      </>
    </div>
  );
};

export default Video;

这可能有两个原因。类似问题已在whosebug.com

中回答

原因一 - 调用暂停而不等待播放承诺解决

原因二 - 在选项卡未获得焦点时调用播放

解决方案如下:

const = videoRef.current;

// Initializing values

    letisPlaying = true;
    
    // On video playing toggle values
    video.onplaying = function() {
        isPlaying = true;
    };
    
    // On video pause toggle values
    video.onpause = function() {
        isPlaying = false;
    };
    
    // Play video function
    function playVid() {      
        if (video.paused && !isPlaying) {
            video.play();
        }
    } 
    
    // Pause video function
    function pauseVid() {     
        if (!video.paused && isPlaying) {
            video.pause();
        }
    }

播放视频时,需要先加载视频,然后才真正播放。如果您在执行此操作时暂停,则会收到错误消息。

解决方案是使用 play 操作返回的承诺,并等待它解决以便暂停。看到这个 article.

const { useRef, useMemo } = React;

const useVideo = (url) => {
  const videoRef = useRef();
  
  const handlers = useMemo(() => {  
    let videoLoaded;
    return {
      start() {
        if(!url || !videoRef.current) return;
      
        videoLoaded = videoRef.current.play()
      },
      pause() {
        if(!url || !videoRef.current) return;
      
        videoLoaded.then(() => {
          videoRef.current.pause();
        });
      }
    }
  }, [url]);

  return {
    videoRef,
    ...handlers
  };
};

const Video = ({ video }) => {
  const { start, pause, videoRef } = useVideo(video.url);
  return (
    <div
      onMouseOver={start}
      onMouseOut={pause}
      onFocus={start}
      onBlur={pause}
      className="col-12"
    >
      <a target="_blank" href={`/videos/${video.id}`} rel="noreferrer">
        <video
          ref={videoRef}
          muted
          height="100%"
          width="100%"
          poster={video.poster}
          src={video.url}
          loop
          preload="auto"
        />
      </a>
    </div>
  );
};

ReactDOM.render(
  <Video video={{ url: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4', id: '' }} />,
  root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>