React Native WebView加载Wistia视频横竖屏切换后回调溢出异常
解决React Native WebView加载Wistia视频横屏关闭后的回调泄漏与UI变形问题
问题根源
横屏切换时,原生控制器触发的布局变更会让WebView内部的UIManager.measureLayout回调被反复注册,但视频关闭后这些回调未被正确清理,累积到阈值就抛出excessive number of pending callbacks: 501异常,同时残留的回调会干扰布局计算导致UI变形。
修复方案
1. 销毁WebView时清理pending回调
利用WebView的原生生命周期回调,手动清除该节点所有未处理的measureLayout回调:
import { UIManager, findNodeHandle, WebView } from 'react-native'; import { useRef } from 'react'; const webViewRef = useRef(null); const cleanupWebViewCallbacks = () => { const nodeHandle = findNodeHandle(webViewRef.current); if (nodeHandle) { UIManager.removeAllMeasureCallbacks(nodeHandle); } }; // 在WebView组件中绑定回调 <WebView ref={webViewRef} source={{ uri: '你的Wistia视频链接' }} onDestroy={cleanupWebViewCallbacks} // Android平台 onWebViewDidClose={cleanupWebViewCallbacks} // iOS平台 />
2. 基于屏幕方向强制WebView重建
通过useWindowDimensions监听屏幕方向变化,给WebView设置唯一key,方向切换时强制组件重建,自动清理旧实例的回调:
import { useWindowDimensions } from 'react-native'; const { width, height } = useWindowDimensions(); const isLandscape = width > height; <WebView key={`wistia-webview-${isLandscape}`} source={{ uri: '你的Wistia视频链接' }} // 其他属性... />
3. 拦截Wistia全屏事件触发布局更新
注入JS脚本监听Wistia视频的全屏状态变化,退出全屏时主动触发WebView的resize事件,避免原生切换导致的回调堆积:
const injectedScript = ` const wistiaPlayer = document.querySelector('.wistia_embed'); if (wistiaPlayer) { wistiaPlayer.addEventListener('fullscreenchange', () => { if (!document.fullscreenElement) { window.ReactNativeWebView.postMessage('exitFullscreen'); } }); } `; const handleWebViewMessage = (event) => { if (event.nativeEvent.data === 'exitFullscreen') { webViewRef.current?.injectJavaScript('window.dispatchEvent(new Event("resize"));'); } }; <WebView ref={webViewRef} source={{ uri: '你的Wistia视频链接' }} injectedJavaScript={injectedScript} onMessage={handleWebViewMessage} />
4. FlatList中优化WebView复用逻辑
给FlatList的每个WebView项设置唯一key,确保组件卸载时能正确执行清理逻辑,避免复用导致的回调泄漏:
const renderVideoItem = ({ item }) => ( <WebView key={item.videoId} source={{ uri: item.wistiaUrl }} onDestroy={cleanupWebViewCallbacks} onWebViewDidClose={cleanupWebViewCallbacks} /> ); <FlatList data={videoList} renderItem={renderVideoItem} keyExtractor={(item) => item.videoId} />
内容的提问来源于stack exchange,提问作者Nensi Kardani
相关产品推荐
相关产品推荐

