React Native使用动画加载器时出现TypeError偶发报错如何解决
问题根因
这个报错是lottie-react-native旧版本的已知竞态问题:组件快速挂载、卸载时,内部原生事件发射器的订阅对象还未完成初始化,就触发了移除订阅的逻辑,读取不存在的nativeEmitterSubscriptionKey属性就会抛出该异常,你频繁刷新页面的操作正好命中了这个场景。你用到的react-native-animated-loader已经多年未维护,底层依赖的是旧版lottie-react-native,所以也会触发相同问题。
解决方案
1. 优先弃用第三方封装库,自行修正Lottie封装逻辑
你自己写的原生Lottie版本存在两个会放大竞态问题的缺陷:Animated.Value未缓存、动画未配置卸载取消逻辑,修正后的组件代码如下:
import React, { useEffect, useRef } from 'react'; import { StyleSheet, View, Animated, Easing } from 'react-native'; import LottieView from 'lottie-react-native'; const Loader = ({ visible }) => { // 用useRef缓存动画值,避免重渲染重复创建实例 const progress = useRef(new Animated.Value(0)).current; const animationRef = useRef(null); useEffect(() => { if (!visible) return; // 显示时重置进度后启动动画 progress.setValue(0); animationRef.current = Animated.timing(progress, { toValue: 1, duration: 5000, easing: Easing.linear, useNativeDriver: true, // 启用原生驱动减少JS线程阻塞,降低竞态概率 }); animationRef.current.start(); // 组件卸载/visible切换时主动取消动画,提前释放资源 return () => { animationRef.current?.stop(); }; }, [visible, progress]); // 不可见时直接返回null,不渲染Lottie组件避免不必要的订阅创建 if (!visible) return null; return ( <View style={styles.container}> <LottieView source={require('../../assets/loader-strange.json')} progress={progress} style={styles.lottie} autoPlay={false} loop={false} // 需要循环播放可改为true,同步调整动画时长和循环逻辑即可 /> </View> ) }; const styles = StyleSheet.create({ container: { // 补充你原来的container布局样式即可 }, lottie: { width: 100, height: 100 } }); export default Loader;
2. 升级lottie-react-native到匹配你Expo版本的稳定版
该竞态问题在新版lottie-react-native中已经被修复,升级时注意和你当前使用的Expo版本匹配,不要跨大版本升级避免出现其他兼容问题。
3. 兜底过滤方案
如果暂时无法升级版本,可以通过全局错误过滤屏蔽该不影响业务的异常:
// App.js入口添加 import { LogBox } from 'react-native'; LogBox.ignoreLogs(['subscription[nativeEmitterSubscriptionKey]']); // 开发环境全局错误捕获过滤 if (__DEV__) { const originalErrorHandler = ErrorUtils.getGlobalHandler(); ErrorUtils.setGlobalHandler((error, isFatal) => { if (error.message?.includes('subscription[nativeEmitterSubscriptionKey]')) return; originalErrorHandler(error, isFatal); }); }
内容的提问来源于stack exchange,提问作者Ivan Ursul
相关产品推荐
相关产品推荐

