实现react-player在视频切换时保持全屏状态
实现React Player全屏状态记忆&解决相关问题
一、核心需求:让下一节课程自动继承全屏状态
其实思路很直白:
- 先监听当前视频的全屏状态变化,把这个状态存在
localStorage(或者你用的全局状态管理工具,比如Context/Redux)里 - 当下一个React Player加载时,读取这个状态,自动帮用户触发全屏
可惜React Player本身没暴露全屏状态的回调,所以得借助浏览器原生全屏API或者第三方库,比如你尝试的screenfull。
二、解决screenfull的编译错误
你碰到的Unexpected token错误,是因为新版screenfull用了ES2020的可选链操作符(?.),但你的Babel配置没支持这个语法。给你两个解决方向:
- 降级到兼容版本:直接装一个不需要新语法的旧版本,比如
npm install screenfull@5.2.0,这个版本兼容性拉满,不用改Babel配置 - 升级Babel配置:如果想追新版,就装
@babel/plugin-proposal-optional-chaining,然后在你的Babel配置文件(.babelrc或者babel.config.js)里加这个插件:
{ "plugins": ["@babel/plugin-proposal-optional-chaining"] }
三、为啥React Player本身有全屏按钮?
React Player的默认控制栏(开启controls属性就会显示)里确实自带全屏按钮,这个是它封装好的UI组件,底层其实也是用全屏API或者screenfull实现的。但它没把全屏状态的变化暴露成回调给咱们用,所以如果要做状态记忆,还是得自己监听全屏事件。
完整实现示例
给你写了个能用的示例,用screenfull@5.2.0+localStorage来实现状态记忆:
- 先装兼容版:
npm install screenfull@5.2.0
- 组件代码:
import React, { useEffect, useRef, useState } from 'react'; import ReactPlayer from 'react-player'; import screenfull from 'screenfull'; const CoursePlayer = ({ videoUrl }) => { const playerRef = useRef(null); const [isFullscreen, setIsFullscreen] = useState(false); // 组件加载时读取之前的全屏状态,自动触发全屏 useEffect(() => { const savedFullscreen = localStorage.getItem('coursePlayerFullscreen') === 'true'; if (savedFullscreen && playerRef.current && screenfull.isEnabled) { // 加个延迟,确保React Player渲染完成再触发全屏 setTimeout(() => { screenfull.request(playerRef.current.wrapper); }, 300); } // 监听全屏状态变化,实时保存到本地 const handleFullscreenChange = () => { const currentState = screenfull.isFullscreen; setIsFullscreen(currentState); localStorage.setItem('coursePlayerFullscreen', currentState.toString()); }; if (screenfull.isEnabled) { screenfull.on('change', handleFullscreenChange); } // 组件卸载时移除监听,避免内存泄漏 return () => { if (screenfull.isEnabled) { screenfull.off('change', handleFullscreenChange); } }; }, [videoUrl]); return ( <div ref={playerRef}> <ReactPlayer url={videoUrl} controls width="100%" height="100%" /> </div> ); }; export default CoursePlayer;
几点说明:
- 用
playerRef抓React Player的外层容器,因为screenfull需要作用在真实DOM元素上 - 初始化时从
localStorage读状态,自动触发全屏(加延迟是为了确保组件渲染完成,避免报错) - 监听
screenfull的change事件,实时更新状态并保存到本地 - 记得在组件卸载时移除监听,不然会有内存泄漏问题
额外提醒
- 部分浏览器对全屏API有安全限制,比如必须通过用户交互(点击按钮之类的)触发,所以自动全屏可能在某些场景下失效,这时候可以加个提示让用户手动点全屏按钮
- 如果你的课程是在同一个页面切换视频(不是刷新页面),用Context或者状态管理存状态会比
localStorage更高效
内容的提问来源于stack exchange,提问作者AlwaysLearning




