React Native Video低iOS版本(<16)失焦无法暂停问题求助
解决iOS 16以下版本useFocusEffect视频暂停失效问题
问题本质
useFocusEffect的清理函数在iOS 16及以下设备上,页面跳转或失焦时无法稳定触发,导致视频无法按预期暂停。这是旧版iOS对React Navigation焦点事件的处理逻辑存在兼容性差异,部分场景下焦点变更事件没有被正确捕获。
兼容解决方案
方案1:结合AppState监听补充控制
利用React Native的AppState监听应用前后台状态,和useFocusEffect形成互补,覆盖低版本iOS的焦点事件遗漏场景:
import { AppState } from 'react-native'; import { useFocusEffect } from '@react-navigation/native'; import React, { useCallback, useEffect, useState } from 'react'; const VideoPlayer = () => { const [appState, setAppState] = useState(AppState.currentState); // 保留原有useFocusEffect逻辑 useFocusEffect( useCallback(() => { if (videoRef.current) { setPlaybackRate(1.0); } return () => { if (videoRef.current) { setPlaybackRate(0); console.log("videoRef!! ", elapsedTime); } else { console.log("Player Destroyed !! ", elapsedTime); console.log("Player Destroyed !! ", videoId, videoName); fetchWatchHistory(phoneNumber, videoId, videoName, elapsedTime, 1); } }; }, [videoRef, elapsedTime]) ); // 新增AppState状态监听 useEffect(() => { const handleAppStateChange = (nextAppState) => { // 应用切后台时强制暂停视频 if (nextAppState === 'background' && videoRef.current) { setPlaybackRate(0); } // 应用回到前台且页面处于焦点时恢复播放 if (nextAppState === 'active' && videoRef.current) { setPlaybackRate(1.0); } setAppState(nextAppState); }; const subscription = AppState.addEventListener('change', handleAppStateChange); return () => subscription.remove(); }, [videoRef]); // 组件其他逻辑... };
方案2:用useIsFocused实时监听焦点状态
放弃依赖useFocusEffect的清理函数,改用useIsFocused钩子实时监听页面焦点状态,主动控制播放/暂停:
import { useIsFocused } from '@react-navigation/native'; import React, { useEffect } from 'react'; const VideoPlayer = () => { const isFocused = useIsFocused(); useEffect(() => { if (!videoRef.current) return; if (isFocused) { setPlaybackRate(1.0); } else { setPlaybackRate(0); if (!videoRef.current) { fetchWatchHistory(phoneNumber, videoId, videoName, elapsedTime, 1); } } }, [isFocused, videoRef, elapsedTime]); // 组件其他逻辑... };
方案3:直接监听页面导航事件
在当前页面监听导航的blur和focus事件,确保页面切换时必触发控制逻辑:
import { useNavigation } from '@react-navigation/native'; import React, { useEffect } from 'react'; const VideoPlayer = () => { const navigation = useNavigation(); useEffect(() => { // 页面失焦时暂停 const blurSubscription = navigation.addListener('blur', () => { if (videoRef.current) { setPlaybackRate(0); console.log("videoRef!! ", elapsedTime); } else { console.log("Player Destroyed !! ", elapsedTime); fetchWatchHistory(phoneNumber, videoId, videoName, elapsedTime, 1); } }); // 页面获焦时恢复播放 const focusSubscription = navigation.addListener('focus', () => { if (videoRef.current) { setPlaybackRate(1.0); } }); return () => { blurSubscription(); focusSubscription(); }; }, [navigation, videoRef, elapsedTime]); // 组件其他逻辑... };
验证要点
- 测试iOS 15及以下设备时,需覆盖页面跳转、应用切后台、锁屏、多任务切换等场景
- 确保
videoRef的引用始终有效,避免组件卸载后引用丢失导致逻辑失效
内容的提问来源于stack exchange,提问作者Crush Khan
相关产品推荐
相关产品推荐

