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

React中使用ReactPlayer无法逐个播放视频数组问题排查

问题根因

当前代码无法自动播放下一个视频的核心问题有3个:

  • 没有维护当前播放视频索引的独立状态,无法追踪当前播放到哪一条
  • 直接把整个URL数组传给ReactPlayer的url属性时,组件默认仅加载数组第一个资源,不会自动轮播
  • 自定义的nextVideo方法逻辑无效:既没有绑定视频播放生命周期事件,item + 1的写法是对数组做隐式类型转换,根本无法获取下一个视频的合法地址,同时初始数据加载时没有做空值判断,首次渲染会触发读空属性的报错。
修复实现

核心修改点

  • 新增currentVideoIndex状态存储当前播放的视频下标,初始值为0
  • 重构URL提取逻辑,直接生成一维的视频地址数组,增加空值兜底避免渲染报错
  • 给ReactPlayer绑定onEnded事件回调:当前视频播放结束时,自动将索引+1切换到下一个视频,到最后一个视频时停止自增避免越界
  • 可选添加上一个/下一个手动切换按钮,支持手动切换
  • 增加空值判断,避免数据未加载完成时的渲染报错

修复后完整代码

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { Button } from "@material-ui/core";
import "./VideoEditorPreview.css";
import ImgCropper from "../Cropper/ImgCropper";
import { assetDownloadUrl } from "../../actions/asset";
import ReactPlayer from 'react-player'

const VideoEditorPreview = ({
  asset,
  dispatch,
  previewFile,
  VideoEditorPreviewWidth,
  VideoEditorPreviewHeight,
  showDia,
  setShowDia,
}) =>
{
  const [data, setData] = useState([])
  // 新增:当前播放视频的索引状态
  const [currentVideoIndex, setCurrentVideoIndex] = useState(0)

  useEffect(() =>
  {
    const timelineData = JSON.parse(localStorage.getItem("timelineFrames"))
    if (timelineData?.[0]?.files) {
      setData([{ items: timelineData[0].files }])
    }
  }, [])

  // 重构:提取扁平化的URL数组,增加空值兜底
  const videoUrls = data.length > 0 && data[0]?.items 
    ? data[0].items.map(file => file.url)
    : []

  // 视频播放结束回调:自动切下一个
  const handleVideoEnd = () => {
    if (currentVideoIndex < videoUrls.length - 1) {
      setCurrentVideoIndex(prev => prev + 1)
    }
  }

  // 手动切上一个
  const handlePrev = () => {
    if (currentVideoIndex > 0) {
      setCurrentVideoIndex(prev => prev -1)
    }
  }

  // 手动切下一个
  const handleNext = () => {
    if (currentVideoIndex < videoUrls.length -1) {
      setCurrentVideoIndex(prev => prev +1)
    }
  }

  return (
    <>
      {/* 手动控制按钮 可根据需求保留或删除 */}
      <div className="video-control-btns">
        <Button 
          variant="contained" 
          onClick={handlePrev}
          disabled={currentVideoIndex === 0}
        >
          上一个视频
        </Button>
        <Button 
          variant="contained" 
          onClick={handleNext}
          disabled={currentVideoIndex === videoUrls.length -1}
        >
          下一个视频
        </Button>
      </div>
      {
        videoUrls.length > 0 && (
          <ReactPlayer 
            id="vid" 
            height="100%" 
            width="100%" 
            url={videoUrls[currentVideoIndex]}  
            controls
            onEnded={handleVideoEnd}
          />
        )
      }
    </>
  );
};

const mapStateToProps = (state) => ({
  asset: state.asset,
});
export default connect(mapStateToProps)(VideoEditorPreview);
补充说明
  • 如果需要实现循环播放,只需要在handleVideoEnd里判断索引到最后一位时,把currentVideoIndex重置为0即可
  • 如果需要视频加载后自动播放,给ReactPlayer加playing={true}属性即可
  • 代码里的可选链?.判断是为了避免首次渲染数据未加载时的空指针报错,如果项目不支持可选链语法,可以替换为普通的多层if判断

内容的提问来源于stack exchange,提问作者Mohit Kushwaha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:03:50