UNPKG

7.81 kBMarkdownView Raw
1# @unimodules/react-native-adapter
2
3A React Native adapter for Expo Universal Modules. It requires [`@unimodules/core`](https://github.com/expo/expo/tree/master/packages/@unimodules/core) to be installed and linked.
4
5## JavaScript installation
6
7```sh
8$ yarn add @unimodules/react-native-adapter
9
10# or
11
12$ npm install @unimodules/react-native-adapter --save
13```
14
15## Installation
16
17If you are using `react-native-unimodules`, this package will already be installed and configured!
18
19### iOS (Cocoapods)
20
21If you're using Cocoapods, add the dependency to your `Podfile`:
22
23`pod 'UMReactNativeAdapter', path: '../node_modules/@unimodules/react-native-adapter/ios', inhibit_warnings: true`
24
25and run `npx pod-install`.
26
27### Android
28
291. Append the following lines to `android/settings.gradle`:
30 ```gradle
31 include ':unimodules-react-native-adapter'
32 project(':unimodules-react-native-adapter').projectDir = new File(rootProject.projectDir, '../node_modules/@unimodules/react-native-adapter/android')
33 ```
342. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
35 ```gradle
36 compile project(':unimodules-react-native-adapter')
37 ```
38
39## Additional required setup
40
41#### iOS
42
431. Open the `AppDelegate.m` of your application.
442. Import `<UMCore/UMModuleRegistry.h>`, `<UMReactNativeAdapter/UMNativeModulesProxy.h>` and `<UMReactNativeAdapter/UMModuleRegistryAdapter.h>`.
453. Make `AppDelegate` implement `RCTBridgeDelegate` protocol (`@interface AppDelegate () <RCTBridgeDelegate>`).
464. Add a new instance variable to your `AppDelegate`:
47
48 ```objc
49 @interface AppDelegate () <RCTBridgeDelegate>
50
51 // add this line
52 @property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter;
53
54 @end
55 ```
56
575. In `-application:didFinishLaunchingWithOptions:` add the following at the top of the implementation:
58 ```objc
59 self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];
60 ```
616. Add two methods to the `AppDelegate`'s implementation:
62
63 ```objc
64 - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
65 {
66 NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge];
67 // If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here!
68 return extraModules;
69 }
70
71 - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
72 return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
73 }
74 ```
75
767. When initializing `RCTBridge`, make the `AppDelegate` a delegate of the bridge:
77 ```objc
78 RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
79 ```
80
81 or, if you use `react-native-navigation`, add the `bridgeManagerDelegate` parameter of `self`, like:
82 ```diff
83 -[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
84 +[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions bridgeManagerDelegate:self];
85 ```
868. That's it! All in all, your `AppDelegate.m` should look similar to:
87
88 <details>
89 <summary>Click to expand</summary>
90 <p>
91
92 ```objc
93 #import "AppDelegate.h"
94
95 #import <React/RCTBundleURLProvider.h>
96 #import <React/RCTRootView.h>
97
98 #import <UMCore/UMModuleRegistry.h>
99 #import <UMReactNativeAdapter/UMNativeModulesProxy.h>
100 #import <UMReactNativeAdapter/UMModuleRegistryAdapter.h>
101
102 @interface AppDelegate () <RCTBridgeDelegate>
103
104 @property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter;
105
106 @end
107
108 @implementation AppDelegate
109
110 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
111 {
112 self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];
113 RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
114 RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"YOUR_MODULE_NAME" initialProperties:nil];
115 rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
116
117 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
118 UIViewController *rootViewController = [UIViewController new];
119 rootViewController.view = rootView;
120 self.window.rootViewController = rootViewController;
121 [self.window makeKeyAndVisible];
122 return YES;
123 }
124
125 - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
126 {
127 NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge];
128 // If you'd like to export some custom RCTBridgeModules that are not universal modules, add them here!
129 return extraModules;
130 }
131
132 - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
133 return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
134 }
135
136 @end
137 ```
138
139 </details>
140
141#### Android
142
1431. Open the `MainApplication.java` of your application.
1442. Add to the imports:
145 ```java
146 import org.unimodules.adapters.react.ModuleRegistryAdapter;
147 import org.unimodules.adapters.react.ReactAdapterPackage;
148 import org.unimodules.adapters.react.ReactModuleRegistryProvider;
149 import org.unimodules.core.interfaces.Package;
150 ```
1513. Create an instance variable on the `Application`:
152 ```java
153 private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(Arrays.<Package>asList(
154 new ReactAdapterPackage()
155 // more packages, like
156 // new CameraPackage(), if you use expo-camera
157 // etc.
158 ), /* singletonModules */ null);
159 ```
1604. Add `new ModuleRegistryAdapter(mModuleRegistryProvider)` to the list returned by `protected List<ReactPackage> getPackages()`.
1615. You're good to go!
162
163## Usage
164
165### Calling methods on native modules
166
167Native modules are available behind the proxy (`NativeModulesProxy` of `@unimodules/core`).
168
169To call an exported method, use `NativeModulesProxy[clientCodeName].exportedMethod(...arguments)`, like this:
170
171```js
172// For UM_REGISTER_MODULE(FileSystem,) or UM_REGISTER_UMPORTED_MODULE(FileSystem)
173// and UM_EXPORT_METHOD_AS(getInfo, getInfo:(NSString *)path)
174
175// or for method
176// @ExpoMethod
177// public void getInfo(String path, Promise promise)
178// defined in native module with name FileSystem
179
180import { NativeModulesProxy } from '@unimodules/core';
181
182const { FileSystem } = NativeModulesProxy;
183
184FileSystem.getInfo('file:///...');
185```
186
187Note that all the methods return `Promise`s.
188
189### Synthetic Platform Events
190
191When creating web universal modules, you may find that you need to send events back to the API layer.
192In this case you will want to use the shared `SyntheticPlatformEmitter` instance from `@unimodules/core`. The shared emitter emit events to `react-native`'s `NativeEventEmitter` and `@unimodules/core`'s `EventEmitter` .
193
194`ExponentGyroscope.web.ts`
195
196```js
197// Example from expo-sensors native web gyroscope sensor
198
199import { SyntheticPlatformEmitter } from '@unimodules/core';
200
201SyntheticPlatformEmitter.emit('gyroscopeDidUpdate', { x, y, z });
202```
203
204This emitted event is then received with a `EventEmitter` in the developer-facing API.
205
206```js
207import { EventEmitter } from '@unimodules/core';
208
209import ExponentGyroscope from './ExponentGyroscope';
210
211const nativeEmitter = new EventEmitter(ExponentGyroscope);
212
213// On Android and iOS, `nativeEmitter` receives events sent from Objective-C and Java. On web, it
214// receives events from the shared `SyntheticPlatformEmitter` instance.
215nativeEmitter.addListener('gyroscopeDidUpdate', ({ x, y, z }) => {});
216```