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

React Native iOS端NativeEventEmitter报addListener不存在错误

问题根因

这个this._nativeModule.addListener is not a function报错仅触发在iOS端,核心原因是React Native iOS平台的NativeEventEmitter初始化逻辑存在强制校验:传入的原生模块必须继承自RCTEventEmitter,并且向JS层暴露addListener、removeListeners两个桥接方法,缺少任意一个就会直接抛出该错误。
Android端事件派发机制不做这个前置校验,只要模块能被NativeModules找到就能正常绑定监听,所以会出现Android运行正常、iOS实例化就报错的现象。
另外你贴的JS代码本身存在逻辑冗余:构造函数接收了module入参,但实际初始化NativeEventEmitter时用的是全局导入的TimJSModule,入参完全没被使用。

可行解决方案

按以下步骤修改即可解决问题:

  • 修正iOS端原生模块实现
    找到iOS目录下TimJs模块的原生代码,把模块的父类从普通的RCTBridgeModule/NSObject改成RCTEventEmitter,同时必须导出addListener、removeListeners两个方法,还要在supportedEvents里声明所有你要发往JS层的事件名。
    如果是Swift实现的原生模块,参考代码如下:
import React

@objc(TimJs)
class TimJs: RCTEventEmitter {
  private var hasListeners = false

  override func supportedEvents() -> [String]! {
    return ["logFromNative", "sdkListener"]
  }

  @objc override func addListener(_ eventName: String!) {
    super.addListener(eventName)
    hasListeners = true
  }

  @objc override func removeListeners(_ count: Double) {
    super.removeListeners(count)
    let currentListenerCount = bridge.value(forKey: "listenerCount") as? Int ?? 0
    hasListeners = currentListenerCount > 0
  }

  // 原有业务方法保留在下方即可
}

如果是Objective-C实现的原生模块,参考代码如下:

#import <React/RCTEventEmitter.h>

@interface RCT_EXTERN_MODULE(TimJs, RCTEventEmitter)

RCT_EXTERN_METHOD(addListener:(NSString *)eventName)
RCT_EXTERN_METHOD(removeListeners:(double)count)

// 原有业务方法的声明保留在下方即可
@end

注意:原生端发送事件时,先判断hasListeners为true再调用sendEvent方法,避免无监听时触发不必要的性能损耗。

  • 修正JS层代码逻辑
    把原来冗余的入参逻辑理顺,同时保存监听订阅实例,增加销毁方法避免内存泄漏,修正后代码如下:
import { NativeEventEmitter, NativeModules, EmitterSubscription } from "react-native";

const TimJSModule = NativeModules.TimJs;

export class ExampleClass {
    private manager: String = "sdkManager";
    private nativeModule: any;
    private logEmitterSubscription?: EmitterSubscription;
    private sdkEmitterSubscription?: EmitterSubscription;

    constructor(module?: any) {
        this.nativeModule = module ?? TimJSModule;
        this.addListener();
    }

    private addListener() {
        const eventEmitter = new NativeEventEmitter(this.nativeModule);
        this.logEmitterSubscription = this.addLogListener(eventEmitter);
        this.sdkEmitterSubscription = this.addSDKListener(eventEmitter);
    }

    private addLogListener(eventEmitter: NativeEventEmitter) {
        return eventEmitter.addListener('logFromNative', (data: any) => {
            const { logs } = data;
            console.log("======log from native module======", logs);
        });
    }

    private addSDKListener(eventEmitter: NativeEventEmitter) {
        return eventEmitter.addListener('sdkListener', (response: any) => {
            // 自定义事件处理逻辑
        });
    }

    // 实例销毁时必须调用该方法移除监听
    destroy() {
        this.logEmitterSubscription?.remove();
        this.sdkEmitterSubscription?.remove();
    }
}
  • 清理缓存重新编译
    原生代码修改后必须清理缓存重新编译,否则改动不会生效,依次执行以下命令:
# 清理Metro缓存
npx react-native start --reset-cache
# 重新安装iOS依赖
cd ios && pod install && cd ..
# 重新运行iOS项目
npx react-native run-ios

不要尝试在JS层手动给原生模块挂载addListener的mock方法,这种方式会导致iOS端原生事件无法正常传递到JS层,属于无效的临时规避方案

内容的提问来源于stack exchange,提问作者joy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:21:27