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

React使用map渲染react-player时点击按钮播放全部而非选中视频的问题

问题原因

  1. 全局共用同一个isPlaying状态,所有ReactPlayer的playing属性都绑定了该值,状态变更会触发所有视频同步播放/暂停
  2. 循环复用单个useRef实例,后续赋值会覆盖之前的引用,最终ref仅指向数组最后一个视频

解决方案

把全局播放状态改为存储「当前正在播放的视频索引」,同时用数组类型的ref存储所有视频的实例引用,点击时仅操作对应索引的状态和ref即可。

修改后完整代码

import React, {useState, useRef} from 'react';
import {useStaticQuery, graphql} from 'gatsby';
import ReactPlayer from 'react-player';
import {Button} from '../Buttons/Button';
import './videos.scss';
import '../../Molecules/Cards/cards.scss';

const VideoCards = () => {
   const { allVideoCardsJson } = useStaticQuery(
        graphql`
          query VideoQuery {
            allVideoCardsJson {
                edges {
                  node {
                    title
                    source
                  }
                }
              }
        }
    `)

    // 存储当前播放的视频索引,null代表无播放视频
    const [playingIndex, setPlayingIndex] = useState(null);
    // 用数组存储所有视频的ref实例
    const videoRefs = useRef([]);
  
    const togglePlay = (index) => {
      // 点击当前正在播放的视频,执行暂停
      if (playingIndex === index) {
        setPlayingIndex(null);
        videoRefs.current[index]?.getInternalPlayer().pauseVideo();
        return;
      }
      // 先暂停之前正在播放的视频
      if (playingIndex !== null) {
        videoRefs.current[playingIndex]?.getInternalPlayer().pauseVideo();
      }
      // 播放当前选中的视频
      setPlayingIndex(index);
      videoRefs.current[index]?.getInternalPlayer().playVideo();
    }

    return (
        <div className="card-container__videos"> 
          {allVideoCardsJson.edges.map(({node, index}) => ( 
          <div className="video-card" key={index}>
               <ReactPlayer 
                  ref={el => videoRefs.current[index] = el}
                  url={node.source}
                  width="100%"
                  pip={true} 
                  controls={true}
                  playing={playingIndex === index}
                ></ReactPlayer>
              
                <Button onClick={() => togglePlay(index)} style={{zIndex:'200'}} label="Play Video"></Button>
                </div>
               ))} 
            </div>
           
    );
};

export default VideoCards;

注意说明

代码中使用?.可选链运算符是为了避免ref未完成挂载时调用方法报错,如果你的项目环境不支持该语法,可以替换为&&判断写法:videoRefs.current[index] && videoRefs.current[index].getInternalPlayer().pauseVideo()

内容的提问来源于stack exchange,提问作者Nikki Peel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:18:02