You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React.js中同类组件如何实现播放视频时自动暂停其他组件播放

问题根源

两个Row组件各自内部维护独立的trailerUrl状态,状态完全隔离,一个Row触发播放时根本感知不到另一个Row的播放状态,自然没法做到自动停止其他行的视频。

实现方法

把播放状态上提到父组件AllRows做全局统一管理,给每个Row传入唯一标识、全局当前播放状态、状态更新回调即可实现互斥播放。

第一步:改造父组件AllRows

父组件存储全局播放状态,记录当前正在播放的视频所属的RowID和视频ID,把状态和更新方法透传给所有子Row:

import React, { useState } from "react";
import Row from "../Components/Row.js";
function AllRows() {
  // 全局播放状态结构:{ rowId: 视频所属行的唯一标识, videoId: YouTube视频ID }
  const [currentPlaying, setCurrentPlaying] = useState(null);
 
  return (
    <div>
      <Row 
        rowId="trending" 
        fetchURL="/trending/all/week" // 替换成你自己Row对应的接口地址
        currentPlaying={currentPlaying}
        onPlayChange={setCurrentPlaying}
      />
      <Row 
        rowId="topRated"
        fetchURL="/movie/top_rated" // 替换成你自己Row对应的接口地址
        currentPlaying={currentPlaying}
        onPlayChange={setCurrentPlaying}
      />
    </div>
  );
}

export default AllRows;

第二步:改造子组件Row

删除组件内部自维护的trailerUrl状态,改为根据父组件传入的全局状态判断是否渲染播放器:

  • 全局状态里的rowId和当前组件rowId匹配时,才渲染对应YouTube播放器
  • 点击海报触发播放时,直接更新全局状态,其他Row检测到当前播放的不是自身内容,会直接卸载YouTube组件,视频自动停止
import React, { useState, useEffect } from "react";
import "../Styling/row.css";
import YouTube from "react-youtube";
import axios from "../Module/axios.js";
import movieTrailer from "movie-trailer"; // 补全你原代码缺失的导入

function Row({ rowId, fetchURL, currentPlaying, onPlayChange }) {
  const base_url = "https://image.tmdb.org/t/p/w500/";
  const [movies, setMovies] = useState([]);
  // 仅当全局播放的视频属于当前行时,才取视频ID
  const trailerUrl = currentPlaying?.rowId === rowId ? currentPlaying.videoId : "";

  useEffect(() => {
    async function fetchData() {
      const request = await axios.get(fetchURL);
      setMovies(request.data.results);
      return request;
    }
    fetchData();
  }, [fetchURL]);

  const opts = {
    height: "390",
    width: "100%",
    playerVars: {
      autoplay: 1,
    },
  };

  const handleClick = (movie) => {
    if (trailerUrl) {
      // 点击当前行正在播放的视频,清空全局播放状态关闭播放器
      onPlayChange(null);
    } else {
      movieTrailer(movie?.name || movie?.title || "")
        .then((url) => {
          const urlParams = new URLSearchParams(new URL(url).search);
          const videoId = urlParams.get("v");
          // 更新全局播放状态为当前行的视频,其他行会自动卸载播放器
          onPlayChange({ rowId, videoId });
        })
        .catch((error) => console.log(error));
    }
  };
  return (
    <div>
      <div className="row__posters">
        {movies.map((movie) => (
          <img
            src={`${base_url}${movie.poster_path}`} // 补全你原代码没写全的海报路径
            key={movie.id}
            alt={movie.title || movie.name}
            className="row__poster"
            onClick={() => handleClick(movie)}
          />
        ))}
      </div>

      {trailerUrl && (
        <YouTube className="row__video" videoId={trailerUrl} opts={opts} />
      )}
    </div>
  );
}

export default Row;
补充说明

你原代码里有几个小疏漏一并修正了:

  • 缺失movieTrailer方法的导入
  • 海报src写的是占位文本,补全了和TMDB图片域名的拼接逻辑
  • 原Row组件内部的fetchURL没有定义,改为父组件传入,避免每个Row写死接口
  • 这个方案不需要额外操作YouTube播放器实例,靠React组件的卸载逻辑就能直接停止视频播放,逻辑最简单也最稳定

内容的提问来源于stack exchange,提问作者Malik Hamza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:36:25