React(Next.js) useRef 问题与视频(npm run build 与 npm run dev)

问题描述 投票:0回答:1

我不知道如何防止

playerRef
clipLink
更改时重新加载。

当我在开发模式下工作时(

npm run dev
),我可以切换视频而无需重新加载
playerRef
。但是,当我在制作模式下工作时(
npm run build && npm start
),我无法在不重新加载的情况下切换视频
playerRef

请假设父组件中有一个按钮,单击时会更改

clipLink
(为简单起见,我从此处的代码中将其删除)

这是父组件

import { useRef } from "react";
import { YouTubePlayer } from 'react-youtube';
import ChildPage from "@/components/ChildPage";

const ParentPage = () => {

  const playerRef = useRef<YouTubePlayer | null>(null);

  return (
    <>
      <ChildPage
        clipLink={clipLink}
        playerRef={playerRef}
      />
    </>
  );
};

export default ParentPage;

这是子组件

import { useEffect } from "react";
import YouTube, { YouTubeProps } from 'react-youtube';

const ChildPage = ({ clipLink, playerRef }) => {

  const onPlayerReady: YouTubeProps['onReady'] = (event) => {
    playerRef.current = event.target;

    event.target.playVideo();
    event.target.setVolume(30);
  };

  const onPlayerStateChange: YouTubeProps['onStateChange'] = (event) => {
    const playerState = event.data;

    switch (playerState) {
      case 0:
        event.target.playVideo();
        break;
      default:
        console.log('Player state changed to:', playerState);
    }
  };

  const opts: YouTubeProps['opts'] = {
    playerVars: {
      autoplay: 1,
      controls: 1,
      fs: 0,
      modestbranding: 1,
      rel: 0,
      iv_load_policy: 3,
    },
  };

  useEffect(() => {
    if (clipLink && playerRef.current) {
      try {
        playerRef.current.loadVideoById(clipLink);
        playerRef.current.playVideo();
        playerRef.current.setVolume(30);
      } catch (error) {
        console.error('Error loading video -', error);
      }
    }
  }, [clipLink]);


  return (
    <>
      <YouTube
        videoId={clipLink}
        opts={opts}
        onReady={onPlayerReady}
        onStateChange={onPlayerStateChange}
      />
    </>
  );
};

export default ChildPage;

如您所见,在子组件中,我有

playerRef.current.loadVideoById(clipLink);

我认为这段代码会在不重新加载的情况下更改

playerRef
的视频,并且它在开发模式下确实按预期工作(
npm run dev
)。

但是,在生产模式下(

npm run build && npm start
),它并不能按预期工作...

reactjs next.js video react-hooks npm-start
1个回答
0
投票

您遇到的问题源于 React 如何处理组件重新渲染和 YouTube 库。当

clipLink
发生变化时,React 会在生产模式下卸载并重新安装 YouTube 播放器,从而导致
playerRef
重置。在开发模式下,React 的热重载行为可能会抑制某些重新安装行为,这可以解释这种差异。

要解决此问题,您必须确保 YouTube 播放器保持安装状态,即使

clipLink
发生变化也是如此。您可以使用播放器的 loadVideoById 方法更新正在播放的视频,而不是卸载和重新安装播放器。

import { useEffect } from "react";
import YouTube, { YouTubeProps } from 'react-youtube';

const ChildPage = ({ clipLink, playerRef }) => {
  const onPlayerReady: YouTubeProps['onReady'] = (event) => {
    playerRef.current = event.target;

    event.target.playVideo();
    event.target.setVolume(30);
  };

  const onPlayerStateChange: YouTubeProps['onStateChange'] = (event) => {
    const playerState = event.data;

    switch (playerState) {
      case 0:
        event.target.playVideo();
        break;
      default:
        console.log('Player state changed to:', playerState);
    }
  };

  const opts: YouTubeProps['opts'] = {
    playerVars: {
      autoplay: 1,
      controls: 1,
      fs: 0,
      modestbranding: 1,
      rel: 0,
      iv_load_policy: 3,
    },
  };

  // UseEffect to update the video when clipLink changes
  useEffect(() => {
    if (playerRef.current && clipLink) {
      const videoId = new URLSearchParams(new URL(clipLink).search).get('v');
      if (videoId) {
        playerRef.current.loadVideoById(videoId);
      }
    }
  }, [clipLink, playerRef]);

  return (
    <YouTube
      videoId={new URLSearchParams(new URL(clipLink).search).get('v') || ""}
      opts={opts}
      onReady={onPlayerReady}
      onStateChange={onPlayerStateChange}
    />
  );
};

export default ChildPage;

© www.soinside.com 2019 - 2024. All rights reserved.