# Bridging Native & React for iOS & Android ## js -> native ### Simple one-off example Keep in mind: - `RCT_EXPORT_METHOD` exposes the name of the method up to the __first__ colon in js land. - When many methods share the same name, use `RCT_REMAP_METHOD` to define a different name for js and map it to the native method. ie. `RCT_REMAP_METHOD(differentMethodName, methodName:(BOOL)arg1 arg2:(BOOL)arg2)`. #### React ```js import { NativeModules } from 'react-native' var videoPlayer = NativeModules.VideoPlayer videoPlayer.seekTo(100) ``` #### iOS [docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#ios-calendar-module-example) ```objc // VideoPlayer.h #import @interface VideoPlayer : NSObject @end @implementation VideoPlayer RCT_EXPORT_MODULE(); // or RCT_EXPLORT_MODULE(AwesomeVideoPlayer) -- custom name RCT_EXPORT_METHOD(seekTo:(double)time) { // seek to time } @end ``` #### Android [docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-android.html#the-toast-module) ```java // VideoPlayer.java package com.beme.react import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; public class VideoModule extends ReactContextBaseJavaModule { public VideoModule(ReactApplicationContext reactContext) { super(reactContext) } @Override public String getName() { return "VideoPlayer"; } @ReactMethod public void seekTo(double time) { // seek to time } } ``` Register the module ```java // VideoPackage.java package com.beme.react import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; public class VideoPackage implements ReactPackage { @Override public List> createJSModules() { return Collections.emptyList(); } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List createNativeModules( ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new VideoModule(reactContext)); return modules; } } ``` ```java // MainApplication.java protected List getPackages() { return Arrays.asList( new MainReactPackage(), new VideoPackage()); // <-- Add this line with your package name. } ``` ### Callbacks #### React ```javascript // index.ios.js videoPlayer.seekTo(100, (error, someData) => { if (error) { console.error(error) } else { console.log(someData) } }) // index.android.js videoPlayer.seekTo( 100, (msg) => { console.error(msg) }, (someData) => { console.log(someData) } ) ``` #### iOS [docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#callbacks) ```objc RCT_EXPORT_METHOD(seekTo:(double)time callback:(RCTResponseSenderBlock)callback) { NSArray *someData; callback(@[[NSNull null], someData]); // (error, someData) in js } ``` #### Android [docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-android.html#callbacks) ```java @ReactMethod public void seekTo(double time, Callback errorCallback, Callback successCallback) { try { successCallback.invoke(someData); } catch (Exception e) { errorCallback.invoke(e.getMessage()); } } ``` ### Promises #### React ```javascript async function loadVideo() { try { var videoLoaded = await VideoPlayer.loadVideo(); this.setState(videoLoaded: videoLoaded) } catch (e) { console.error(e) } } loadVideo() ``` #### iOS [docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#promises) ```objc RCT_REMAP_METHOD(loadVideo, loadVideoResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { BOOL videoLoaded = ... if (videoLoaded) { resolve(videoLoaded); } else { NSError *error = ... reject(@"error", @"error description", error); } } ``` #### Android ```java ``` ### Properties (UI) ## native -> js ### Events Keep in mind: - Events share namespace (so come up with a naming convention) - If you have several instances of a component, you need to pass an identifier (like a view's `reactTag`) to identify it in the handler. ## Additional Resources