react navite原生事件监听、全局事件通知

在 React Native(RN)里,"原生事件监听"和"全局事件通知"通常分两类:

  1. Native → JS 事件通知(原生主动通知 RN)
  2. JS 全局事件总线(RN 内部模块间通信)

下面分别讲。


一、Native → JS 原生事件监听

典型场景:

  • Android 原生收到推送
  • 蓝牙状态变化
  • GPS 定位变化
  • 登录状态变化
  • 支付结果回调
  • 原生 SDK 回调

流程:

yaml 复制代码
Android/iOS
    |
    | sendEvent
    ↓
React Native Bridge / JSI
    |
    ↓
JavaScript EventEmitter
    |
    ↓
addListener()

Android 示例

1. 原生 Module 发送事件

Java:

scala 复制代码
public class MyNativeModule extends ReactContextBaseJavaModule {

    private ReactApplicationContext context;

    public MyNativeModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.context = reactContext;
    }


    @Override
    public String getName() {
        return "MyNativeModule";
    }


    public void sendLoginEvent(String token) {

        context
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit(
            "LoginSuccess",
            token
        );
    }
}

这里:

scss 复制代码
emit(
 "LoginSuccess",
 token
)

就是发送 RN 事件。


2. JS 监听

javascript 复制代码
import {
 DeviceEventEmitter
} from 'react-native';


useEffect(()=>{


 const listener =
 DeviceEventEmitter.addListener(
   'LoginSuccess',
   (token)=>{

      console.log(
        "登录成功",
        token
      );

   }
 );


 return ()=>{

    listener.remove();

 }


},[])

效果:

makefile 复制代码
Android:
emit("LoginSuccess","abc")


JS:

收到

token="abc"

iOS 示例

Objective-C:

objectivec 复制代码
#import <React/RCTEventEmitter.h>


@interface MyEventEmitter : RCTEventEmitter

@end



@implementation MyEventEmitter


RCT_EXPORT_MODULE();



- (NSArray<NSString *> *)supportedEvents
{
    return @[
        @"LoginSuccess"
    ];
}



- (void)sendLogin:(NSString *)token
{

 [self sendEventWithName:
        @"LoginSuccess"
        body:token];

}


@end

JS:

ini 复制代码
import {
 NativeEventEmitter,
 NativeModules
} from 'react-native';


const emitter =
new NativeEventEmitter(
 NativeModules.MyEventEmitter
);


const sub =
emitter.addListener(
 "LoginSuccess",
 token=>{
    console.log(token)
 }
);


sub.remove();

二、RN 内部全局事件通知

比如:

css 复制代码
页面A登录

        ↓

通知

        ↓

页面B刷新用户信息

不需要 Native。

常用方案:


方案1:EventEmitter 全局事件总线

安装:

复制代码
npm install eventemitter3

创建:

bash 复制代码
src/utils/EventBus.js
arduino 复制代码
import EventEmitter from 'eventemitter3';


export default new EventEmitter();

发送:

python 复制代码
import EventBus from './EventBus';


EventBus.emit(
 "USER_LOGIN",
 {
   id:100
 }
);

监听:

javascript 复制代码
import EventBus from './EventBus';


useEffect(()=>{


 const handler=(user)=>{

    console.log(user)

 }


 EventBus.on(
   "USER_LOGIN",
   handler
 );


 return ()=>{

   EventBus.off(
     "USER_LOGIN",
     handler
   );

 }


},[])

结构:

scss 复制代码
        EventBus

 A页面
 emit()

       |
       |
       ↓

 USER_LOGIN


       |
       |
       ↓


 B页面
 on()

三、React Native 推荐方案

现在 RN 项目一般不会大量使用 EventBus。

更推荐:

场景 推荐
组件状态共享 Zustand
复杂业务状态 Redux Toolkit
服务器数据 React Query
Native通知JS NativeEventEmitter
简单跨页面通知 EventEmitter

例如登录:

不推荐:

csharp 复制代码
LoginPage

EventBus.emit("LOGIN")

HomePage

EventBus.on("LOGIN")

推荐:

csharp 复制代码
             Zustand

login()
  |
  |
 user={name:"张三"}

  |
  |
所有组件自动更新

四、RN 新架构 Fabric / TurboModule 下

你之前问过 Fabric,这里补充:

旧架构:

arduino 复制代码
Native
 |
Bridge
 |
JS

事件:

scss 复制代码
emit()
 ↓
Bridge Queue
 ↓
JS EventEmitter

新架构:

yaml 复制代码
Native Module
       |
       |
     JSI
       |
       |
 JavaScript Runtime

通信更直接。

但是:

  • DeviceEventEmitter
  • NativeEventEmitter

仍然大量存在。

TurboModule 推荐:

php 复制代码
interface Spec extends TurboModule {

 addListener(
   eventName:string
 ):void;


 removeListeners(
   count:number
 ):void;

}

然后:

arduino 复制代码
NativeModule.addListener(
 "EVENT"
)

五、实际项目架构建议

例如 App:

markdown 复制代码
                 Native


 推送SDK
 蓝牙SDK
 支付SDK
 登录SDK

       |
       |
       ↓


 NativeEventEmitter


       |
       |
       ↓


 event adapter


       |
       |
       ↓


 Zustand / Redux


       |
       |
       ↓


 React Components

不要让页面直接监听 Native。

推荐:

复制代码
Native
 ↓
Service层
 ↓
Store
 ↓
页面

这样维护性最好。


如果你是想实现类似微信桌面端扫码登录那种"原生扫码成功通知 RN 页面刷新" ,一般就是 NativeEventEmitter + 状态管理(Store) 这一套。你前面问过微信扫码登录,这个场景正好对应。

相关推荐
lvv1 小时前
不会被渲染的组件,为什么让我的首屏白屏了?(一次前端问题总结)
前端·webpack·性能优化
烬羽1 小时前
《memo 明明加了,为什么子组件还是渲染了?》
react.js·性能优化·全栈
码上成长1 小时前
微前端 Invalid hook call?先把「window 注入 + externals」整明白
前端·react.js·前端框架
宿6741 小时前
vue3-DOM树
前端·javascript·vue.js
白狐_7982 小时前
408数据结构:中缀转后缀与操作符栈容量——真题精讲
前端·javascript·数据结构
谷哥的小弟2 小时前
TypeScript在Vue3中的常见写法
前端·javascript·typescript
人间凡尔赛2 小时前
2026 前端全栈新范式:Server Actions + Edge Runtime,告别传统 API 路由
前端·全栈·next.js
小月土星3 小时前
useCallback 深度解析:React 性能优化的核心利器
react.js·前端框架
码林鼠5 小时前
2026前端面试题(二)
前端