According to React Native documentation, you can use sendAppEventWithName
to send an event from native code to JS. But in my XCode, code suggestions tell me that this method is deprecated.
This issue indicates that sendDeviceEventWithName
should work but actually it's also deprecated.
What is the proper way to send an event to JS?
I figured it out by reading its source code. Using the RCTEventEmitter
class.
MyModule.h
#import "RCTEventEmitter.h"
#import "RCTBridgeModule.h"
@interface MyModule : RCTEventEmitter <RCTBridgeModule>
@end
MyModule.m
@implementation MyModule
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"sayHello"];
}
- (void)tellJS () {
[self sendEventWithName:@"sayHello" body:@"Hello"];
}
@end
So you can send an event called sayHello
with data Hello
to JavaScript by calling the tellJS
method.
In JavaScript side, you have to use the NativeModules
module to get this native module and wrap it in NativeEventEmitter
class so that you can receive events.
import { NativeModules, NativeEventEmitter } from 'react-native'
const myModuleEvt = new NativeEventEmitter(NativeModules.MyModule)
myModuleEvt.addListener('sayHello', (data) => console.log(data))
@livoras
First issue, shouldn't:
[sendEventWithName:@"sayHello" body:@"Hello"];
Be:
[self sendEventWithName:@"sayHello" body:@"Hello"];
Second issue: RCTEventEmitter.m is throwing an error:
- (void)sendEventWithName:(NSString *)eventName body:(id)body
{
RCTAssert(_bridge != nil, @"bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.", [self class]);
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
eventName, [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]);
}
if (_listenerCount > 0) {
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
args:body ? @[eventName, body] : @[eventName]];
} else {
RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName);
}
}
_bridge is nil and it's throwing an exception. Should we open another ticket on fixing the documentation on the proper way to do this? I think it's still not fully clear.
I have the same problem, the bridge is nil. Have you resolve it? @joekim
@purplepeng I ended up just creating a native module and using callbacks instead of using events. Haven't tested it again recently.
I got it to work in swift... here is the snippets
// in my module...
@objc(YourModule)
class YourModule: RCTEventEmitter {
override func supportedEvents() -> [String]! {
return ["UploadProgress"]
}
further down in the class
// A progress event occurred, notify the user...
uploadTask.observeStatus(.Progress) { (snapshot:FIRStorageTaskSnapshot) in
if let progress = snapshot.progress {
let percentComplete = Double(progress.completedUnitCount) / Double(fs)
let ret : [String:AnyObject] = [
"completedUnitCount": String(progress.completedUnitCount),
"percentComplete": String(percentComplete),
"totalUnitCount": String(fs)
]
self.sendEventWithName("UploadProgress", body: ret )
}
}
In my react-native code
const myModuleEvt = new NativeEventEmitter(NativeModules.YourModule)
var subscription = myModuleEvt.addListener(
'UploadProgress',
(progress) => {
console.log("UploadProgress")
console.log(JSON.stringify(progress, null, 2))
}
);
@joekim @aaronksaunders @livoras Thank you. It works for me. I realized the process of sent event from native to JS in two separate module before, so it doesn't work.
so , the start of 'send event from iOS to javascript' is still javascript,am i right? 3Q
what about android? this seems to create module scoped events, but how do we do this in android?
@purplepeng can you explain what you meant by "I realized the process of sent event from native to JS in two separate module before, so it doesn't work."
I am trying to send an event to JS and keep seeing the error that the bridge is not set.
@aaronksaunders thanks for tip but how to deal a viewmanager in the same time?
@objc(RNAnalogClockSwift)
class RNAnalogClockManager: RCTViewManager, RCTEventEmitter {
throws: Multiple inheritance from classes 'RCTViewManager' and 'RCTEventEmitter'
Sorry, I'm a bit confused how to deal sending event since this deprecation.
Previous way was far easier to figure out and implement.
@andybangs
I have resolved the problem with following code.
#import "RCTBridgeModule.h"
#import "RCTEventEmitter.h"
@interface RCTUserManager : RCTEventEmitter <RCTBridgeModule>
@end
@implementation RCTUserManager
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[AuthorizationWasFailedNotification,AuthorizationWasSucceedNotification,AuthorizationWasInvalidNotification,AuthorizationWasCancelledNotification];
}
RCT_EXPORT_METHOD(signinWithUserName:(NSString *)userName
password:(NSString *)password
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.userModel signinWithUserName:userName
password:password
completion:^(STIHTTPResponseError *e) {
if ( e ) {
NSError * error;
reject([NSString stringWithFormat:@"%@",@(e.code)],e.message,error);
}
else
{
NSDictionary * data = @{@"token":self.userModel.token,@"user":[self.userModel.user JSONStringRepresentation]};
resolve([data JSONStringRepresentation]);
[self sendEventWithName:AuthorizationWasSucceedNotification body:[data JSONStringRepresentation]];
}
}];
}
But,I added
[self sendEventWithName:AuthorizationWasSucceedNotification body:[data JSONStringRepresentation]];
in other module before,not in this RCTUserManager
,so it didn't work. Hope can help you.
@purplepeng it looks like you are subclassing RCTEventEmitter, but actually using a promise to interact with React Native. Are you successfully listening to your [self sendEventWithName:body:];
call in JS, or just relying on your promise resolve block? Or both?
@andybangs
Both. In my react-native code, the part of event as below:
componentDidMount() {
const authModuleEvent = new NativeEventEmitter(NativeModules.UserManager)
signinSubscription = authModuleEvent.addListener('AuthorizationWasSucceedNotification',
(reminder) => {
...
});
}
componentWillUnmount() {
signinSubscription.remove();
}
@purplepeng any word on how to do this on the android side?
bridge still nil. What is wrong with this?
#import "RCTBridgeModule.h"
#import "RCTEventEmitter.h"
@interface HelperManager : RCTEventEmitter <RCTBridgeModule>
- (void)sendURLSchemeParameters:(NSURL *)url;
@end
#import "HelperManager.h"
@implementation HelperManager
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"URL_SCHEME"];
}
RCT_EXPORT_METHOD(sendURLSchemeParameters:(NSURL *)url) {
[self sendEventWithName:@"URL_SCHEME" body:@{}];
}
@end
Can we please have an insight on how to handle this now? I made a bridge using the doc but knowing that this method is deprecated, I'm not really confident...
I think this needs to be documented as this means every lib using this are going to break when the update removing the support of the deprecated methods is going to land!
@lazarte @julien-rodrigues: Here is a stripped down version of a functioning subclass of RCTEventEmitter in my app: https://gist.github.com/andybangs/c4651a3916ebde0df1c977b220bbec4b
@andybangs Thanks a lot for your gist. I'm a complete noob in Objective C but this is exactly what I'm trying to achieve.
I'm receiving a Firebase dynamic link on application's openUrl
and I need to be able to fire an event with the "decoded" link that my RN bridge would listen and forward it to the JS side.
I have 2 question tho. Do you start listening on the Objective C event in the init
of your class?
And when do you fire the method to the NotificationCenter?
Thanks again
@andybangs Just tried to replace my implementation with yours and I keep having this:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'bridge is not set. This is probably because you've explicitly synthesized the bridge in TestClass, even though it's inherited from RCTEventEmitter.
@julien-rodrigues
startListening
method to be called in a RN component’s componentWillMount
methodTo continue with my example above, I am not explicitly instantiating my GSEventEmitter class anywhere because RN creates the instance for me. I import the GSEventEmitter header file in whatever other class I want to emit an event from to use it. Here is another stripped down gist of how I am doing this: https://gist.github.com/andybangs/5f1ee78247b0346e24d55119c6a02afa
Hope this helps, and let me know if you have any other questions.
@andybangs Thanks a lot for your time 👍
Yes that's really more clear to me now lol
This implementation is different from what I've done and I understand now why I got conflicts.
I was trying to go full native. I was attaching the listener by myself in AppDelegate and then fired the event when the FirebaseSDK was done computing the incoming link. Which then fired the JS event. So either the event was fired before the JS side was listening or the JS handler was not attached on the right instance(?, don't know if that's possible).
Either way I like your idea, I'm going to try it out. Thanks for sharing
Facing the same problem, subclassed the RCTEventEmitter but stuck on the bridge is nil assertion error (bridge is not set. This is probably because you've explicitly synthesized the bridge in ReactNativeEventManager, even though it's inherited from RCTEventEmitter.
).
#import <React/RCTEventEmitter.h>
@interface ReactNativeEventManager : RCTEventEmitter
-(void)postEvent:(NSNotification *)notification;
@end
#import "ReactNativeEventManager.h"
@implementation ReactNativeEventManager
RCT_EXPORT_MODULE();
-(void)postEvent:(NSNotification *)notification {
NSString *eventName = notification.userInfo[@"name"];
[self sendEventWithName:eventName body:[notification userInfo]];
}
- (NSArray<NSString *> *)supportedEvents {
return @[@"add-exchange", @"open-exchange"];
}
@end
Anybody an idea on how to solve this? Did try all of the above solutions, but none of them seem to work. :(
@VincentdeWit94 did you check out the gists I posted above that utilize NSNotificationCenter?
Example subclass of RCTEventEmitter: https://gist.github.com/andybangs/c4651a3916ebde0df1c977b220bbec4b
Example usage: https://gist.github.com/andybangs/5f1ee78247b0346e24d55119c6a02afa
This entire thread has been helpful, appreciate it, but I'm not quite there yet.
@andybangs if I'm not mistaken you created a .m file just for raising the event (handleBeaconSightingNotification); then you import that into your .m file that will emit the event calling the GSEventEmitter method???
@TheoGit that sounds about right. It may not be how usage is shown in the docs, but is the solution I'm currently relying on to get past that "bridge is not set..." error that others have also posted about here.
My subclass of RCTEventEmitter, GSEventEmitter, is modeled after how RCTLinkingManager in the RN codebase subclasses RCTEventEmitter. Although the code itself is not up to date, the idea to try this came from the accepted answer of this SO post: http://stackoverflow.com/questions/36092903/listening-for-events-in-react-native-ios.
In my application, GSEventEmitter handles all native events that need to be emitted to JS, so I import and use GSEventEmitter.h in a number of other classes. In the example above I use it in GSBeaconManager.m to emit beacon sightings with the following call:
[GSEventEmitter application:[UIApplication sharedApplication] beaconSighted:beaconID];
Here is another example:
I already have native code for registering notification settings, so instead of using the RN PushNotificationIOS abstraction, I use my Objective-C code and a method I define in GSEventEmitter called + (BOOL)application:(UIApplication *)application notificationsRegistered:(UIUserNotificationSettings *)notificationSettings;
that I call in my AppDelegate and listen for in JS.
// AppDelegate.m
...
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[GSEventEmitter application:[UIApplication sharedApplication]
notificationsRegistered:notificationSettings];
}
...
// Welcome.js
...
componentWillMount() {
const { GSEventEmitter } = NativeModules;
const { NOTIFICATIONS_REGISTERED, SIGHTED_BEACON } = GSEventEmitter;
const { addBeacon } = this.props.actions;
this.eventEmitter = new NativeEventEmitter(GSEventEmitter);
this.eventEmitter.addListener(NOTIFICATIONS_REGISTERED, this.handleNotificationsRegistered);
this.eventEmitter.addListener(SIGHTED_BEACON, (data) => addBeacon(data.payload));
}
componentDidMount() {
const { GSNotificationManager } = NativeModules;
GSNotificationManager.registerNotifications();
}
componentWillUnmount() {
this.eventEmitter.remove();
}
handleNotificationsRegistered() {
const { GSBeaconManager } = NativeModules;
GSBeaconManager.startListening();
}
...
@andybangs I really appreciate the time/explanation - will do my best to reproduce this; the only part confusing for me is the delegate (GMBLBeaconManagerDelegate) - thank you again!
@TheoGit: No problem. I included the GMBLBeaconDelegate protocol only as an example of how I am using my subclass of RCTEventEmitter. In that example, the method – beaconManager:didReceiveBeaconSighting:
tells the instance of GMBLBeaconManager when a beacon is sighted. The relevant part to this discussion, is the call in that method [GSEventEmitter application:[UIApplication sharedApplication] beaconSighted:beaconID];
which emits an event that I am listening for in JS.
@livoras Thank you. It works for me.
@andybangs this is working; I had to make a few tweaks (like NativeAppEventEmitter instead of NativeEventEmitter) but overall it was your suggestion of subclassing RCTEVentEmitter that I finally understood after reading and re-reading; thanks again this thread as been invaluable.
@andybangs your example worked for me.
@andybangs
Actually, no need to use NotificationCenter, RCTBridge has a method called module(for: AnyClass),
which can get an instance of RCTEventEmitter, then you can call your fuction to send event
@hitbear518 Can you give more insights on how to use module(for: ) and get the instance of RCTEventEmitter? Thanks a lot
@xaviraol Here's what i did:
class FooModule: RCTEventEmitter {
...
}
@interface RCT_EXTERN_MODULE(FooModule, NSObject)
...
@end
3.get the RCTBridge(I saved it as singleton), then get the module to send event
if let fooModule = MyRCTBridgeDelegate.sharedInstance.bridge.module(for: FooModule) as? FooModule {
fooModule.sendMyEvent()
}
then you can subscript the event from js code
Also, checkout the master branch doc in react-native official site for more info:
Sending Events to JavaScript
thanks @hitbear518 !!!
@hitbear518 would it be possible to provide a more complete example of your implementation?
@aaronksaunders How are you instantiating the RCTEventEmitter (YourModule)? I have my code pretty much exactly the same as yours, but if I instantiate MyEventEmitter, the bridge variable is null and the app crashes. I've read that I should "let react instiatate modules" but I'm not quite clear on how to do this. It seems possible in ObjeC but how to do it in Swift?? I'm missing something simple I'm sure, any help would be appreciated.
@hitbear518 I make it out,thanks.
@aaronksaunders You shouldn't instantiate your emitter yourself. Look here.
"When you used the macro RCT_EXPORT_MODULE() React-Native will instantiate the class for you, and any subsequent alloc/inits will create new instances, unrelated the original. The bridge will not be instantiated in these new instances."
The solution is to override startObserving and stopObserving and listen to NSNotifications.
I used both Objective-C and Swift to test, but I still get "_bridge is nil and it's throwing an exception"
Here's what I did:
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface RNEventManager : RCTEventEmitter <RCTBridgeModule>
@end
// RNEventManager.m
#import "RNEventManager.h"
@implementation RNEventManager
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"ExportDescriptionViewWillAppear"];
}
@end
And I called sendEventWithName:body:
in viewWillAppear
of ExportDescription.
So did I miss something?
Okay, I seem to have managed to get it to work using Swift. It's almost the same as @hitbear518 proposed.
EventEmitter.swift
@objc(EventEmitter)
class EventEmitter: RCTEventEmitter {
@objc
override func supportedEvents() -> [String] {
return ["event1", "event2"]
}
}
EventEmitterBridge.m
#import "React/RCTEventEmitter.h"
@interface RCT_EXTERN_MODULE(EventEmitter, RCTEventEmitter)
@end
And then in my other module I'm doing something like this:
MyOtherModule.swift
var bridge: RCTBridge!
@objc(MyOtherModule)
class MyOtherModule {
func sendSomeEvent() {
if let eventEmitter = bridge.module(for: EventEmitter.self) as? EventEmitter {
self.sendEvent(withName: "event1", body: "Woot!")
}
}
}
I don't have a single clue how and why this is working since my iOS / Swift knowledge is basically non-existent, but apparently, the var bridge: RCTBridge!
object gets somehow synthesized (is that what this is called?) so it is available in MyOtherModule
.
I'm also not sure if I used the module(for:)
thingy correctly but it seems to work.
As mentioned before the EventEmitter
should not be instantiated manually.
@sandromartis you should have your "MyOtherModule" inherit RCTEventEmitter (you kind of did with the EventEmitter class already). Then you can use sendEvent
from there.
There must be something missing from the code example you've given because I don't understand why bridge: RCTBridge!
is available in MyOtherModule
.
@chourobin The thing is that I cannot make MyOtherModule
inherit from RCTEventEmitter
because it is already inheriting from RCTViewManager
.
That's why I created a new module EventEmitter
that inherits from RCTEventEmitter
which creates the whole problem of accessing it in MyOtherModule
.
So MyOtherModule
actually looks like this:
var bridge: RCTBridge!
@objc(MyOtherModule)
class MyOtherModule: RCTViewManager {
func sendSomeEvent() {
if let eventEmitter = bridge.module(for: EventEmitter.self) as? EventEmitter {
self.sendEvent(withName: "event1", body: "Woot!")
}
}
}
Now that I'm writing this I realize that bridge: RCTBridge!
is available in MyOtherModule
because that one is inheriting from RCTViewManager
. Also bridge: RCTBridge!
is actually not necessary and you can just use self.bridge.module(for: EventEmitter.self)
.
I assume that if you don't have an RCTViewManager
you probably have to set the bridge to a global value in AppDelegate.m
to make this work. Something like this:
_AppDelegate.h_
@property (nonatomic, strong) RCTBridge *bridge;
_AppDelegate.m_
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"LayerTwo"
initialProperties:nil
launchOptions:launchOptions];
bridge = rootView.bridge;
...
}
@end
Let me know if that makes sense or if I'm talking complete bullshit here. I'm totally new to all this react-native and native iOS development stuff.
@sandromartis nope that makes sense. just fyi, there is another api for sending events from ui-based modules, and it's by using RCTBubblingEventBlock
or RCTDirectEventBlock
. I had a gist that summarizes some of this info if it's helpful:
https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-events-ui-md
I subclassed RCTEventEmitter
for a background timer and for some reason the events fire in the background in the emulator but not on my real iOS device. Does anyone know why this happens? sendDeviceEventWithName
works perfectly but it sends a deprecation warning.
Finally, I got the solution.
#import "RNNotification.h"
@implementation RNNotification
RCT_EXPORT_MODULE();
+ (id)allocWithZone:(NSZone *)zone {
static RNNotification *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}
- (void)sendNotificationToReactNative
{
[self sendEventWithName:@"EventReminder" body:@{@"name": @"name"}];
}
When you use it!
RNNotification *notification = [RNNotification allocWithZone: nil];
[notification sendNotificationToReactNative]
I fix this problem by:
return @[@"CancelEvent", @"OKEvent"];
}
Globally , call delegate.MyViewController 's function to send events;
@Liqiankun Your solution Works like a charm . Much Appreciated :)
This doesn't seem to work on versions before 0.47.0.
Its easily reproducible:
react-native init TestProject --version [email protected]
Tested on the same app with version 0.49.0 and it works like a charm.
I could be wrong but I believe it has to do with these breaking changes (https://github.com/facebook/react-native/commit/ce6fb337a146e6f261f2afb564aa19363774a7a8, https://github.com/facebook/react-native/commit/53d5504f4077bf7fb7cbf7c1edac7e2cbde5c964)
Can someone comment on this?
This may help you.
BKLEventEmitter.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface BKLEventEmitter : RCTEventEmitter <RCTBridgeModule>
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload;
@end
BKLEventEmitter.m
@implementation BKLEventEmitter
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
// register name, may be more...
return @[@"NotificationName"];
}
- (void)startObserving {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
for (NSString *notificationName in [self supportedEvents]) {
[center addObserver:self
selector:@selector(emitEventInternal:)
name:notificationName
object:nil];
}
}
- (void)stopObserving {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)emitEventInternal:(NSNotification *)notification {
[self sendEventWithName:notification.name
body:notification.userInfo];
}
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload {
[[NSNotificationCenter defaultCenter] postNotificationName:name
object:self
userInfo:payload];
}
@end
Finally use it!! You must ensure that the name is already registered.
[BKLEventEmitter emitEventWithName:@"NoticationName" andPayload:nil];
@ZionChang Great piece of code!!
Unfortunately, it was my ignorance that left out an integral piece of code in the new 0.46.0 RN app I made. Regardless, I like the static method calls much more than having an extra object. Much appreciated
@ZionChang this looks really good but how do you call the instance method startObserving
? I'm pretty new to Objective-C so it's not clear to me.
@ZionChang I read the code for RCTEventEmitter and saw that the startObserving
method is called when you call addListener
from JavaScript.
My issue is I'm emitting the event before the listener was attached!
Working on it...
@niksoper no need to call addListener
which is called in react-native
source code, just call emitEventWithName
.
just starting out using events to communicate from objective-c to js. this is all pretty confusing at the moment. I have a "working" version but I don't understand it since I have to use NativeEventEmitter
and DeviceEventEmitter
to receive events from objective-c:
const communicationModuleEmitter = new NativeEventEmitter(CommunicationModule);
const subscription = communicationModuleEmitter.addListener(
'genericLogEvent',
(e) => console.log('got a genericLogEvent: ', e), // <--- this is NOT called but somehow needed
);
along with
const subscribeForNativeEvents = (eventID, callback) => {
LOG_S().d('Subscribing to ' + eventID);
DeviceEventEmitter.addListener(eventID, callback);
};
subscribeForNativeEvents('genericLogEvent', (event) => {
console.log('got a generic event!!!', event); // <--- this is actually called
});
this is the native objective-c side:
RCT_EXPORT_METHOD(foo)
{
RCTLogInfo(@"foo");
[self emitMessageToRN:@"genericLogEvent" :@{ @"logMessage": @"event from foo" }];
}
- (void) emitMessageToRN: (NSString *)eventName :(NSDictionary *)params {
[self sendEventWithName: eventName body: params];
}
this setup will give me the following result:
D got a generic event!!! "type is: object : {"logMessage":"event from foo"}"
anyone knows why I need to subscribe both with DeviceEventEmitter
and NativeEventEmitter
? I tried to find documentation on this but haven't found a lot.
@ZionChang but with no listeners the event will be useless and emitEventWithName
will go nowhere.
My reading of the RCTEventEmitter source tells me that startObserving
will only be called once you've added a listener in JavaScript - which is presumably an optimisation:
RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
{
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
eventName, [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]);
}
_listenerCount++;
if (_listenerCount == 1) {
[self startObserving];
}
}
I know that, like I said, such as you can call [BKLEventEmitter emitEventWithName:@"NoticationName" andPayload:nil];
in viewDidAppear
which is a native method of UIViewController
. And method named addListener
will be called by react-native
automatically. You can have a try and make a breakpoint to test it.
@niksoper
Most helpful comment
I figured it out by reading its source code. Using the
RCTEventEmitter
class.MyModule.h
So you can send an event called
sayHello
with dataHello
to JavaScript by calling thetellJS
method.In JavaScript side, you have to use the
NativeModules
module to get this native module and wrap it inNativeEventEmitter
class so that you can receive events.