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
相关产品推荐
相关产品推荐

