You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 23:36:03