Integrating React-Native in an existing application is a smart way to increase your development speed. It increases the complexity of your application but allows you to implement your component once for both platforms.
There is a great official tutorial to do this. Here are few aditional tips to improve your chance of success.
React-native have the following requirement to works :
To be able to use the react native CLI, you will need to structure your app to match the folder architecture of a normal react-native project :
++pre>++code>node_modules/
ios/
android/
react-native/
index.js
index.android.js
index.ios.js
package.json
++/code>++/pre>
If you want to keep your VCS history in your native app, you can use submodule for the folder ++code>ios++/code> and ++code>android++/code>. But if you do, you now have 2 projects that need a third one to work.
You may have issues with dependencies on android. React-native is edited by facebook. So installing react-native may lead to duplicates gradle dependencies with other facebook libraries.
You will maybe have to exclude some parts of your dependencies :
++pre>++code> compile ('com.facebook.android:facebook-android-sdk:4.7.0') {
exclude module: 'bolts-android'
}
compile 'com.facebook.react:react-native:0.41.2' // From react-native node_modules.
++/code>++/pre>
If you have issues like :
++pre>++code>java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.bamlab.reactIntegration/lib-main/libgnustl_shared.so" is 32-bit instead of 64-bit
++/code>++/pre>
The solution is in one of our special blog article about fix permission in android
It is easier to create a page at the end of the flow rather than a component in the middle of an existing page.
If you are experimenting, start by doing simple things.
You will also have less issues preloading the native content and managing the navigation.
You will need to create React-Native modules to share data or components between your native code and your javascript code. You can find resources both for android and ios in the official documentation.
If you call a native method from react, be careful that the native code and the javascript run in separate threads. This means that you can't interact with displayed native components directly from a bridge method.
On iOS, to avoid the thread related issues, you have to use the ++code>dispatch_async++/code> function :
++pre>++code>RCT_EXPORT_METHOD(mySharedMethod) {
dispatch_async(dispatch_get_main_queue(), ^{
[[MyNativeService instance] myNativeMethod];
});
}
++/code>++/pre>
When you are installing an external native module for react-native, follow the manual installation instruction of the dedicated module.
In android, you will need to add a ++code>.addPackage(new MyLib())++/code> call at every place you integrated a react-native content and you want to use the plugin (with a ReactInstanceManager).
If you don't, it will work on debug but not on release.
The bundled assets are generated with the same command as the javascript.
In android, send the output to ++code>/src/main/res/++/code> and everything will be fine.
In ios, you must drag and drop the bundler output in the same folder as the javascript on xCode. Then select to not copy file and create folder references
Just use the ++code>AppRegistry++/code>.
In the javascript :
++pre>++code>import React from 'react';
import { AppRegistry } from 'react-native';
import MyPage1 from './src/MyPage1';
import MyPage2 from './src/MyPage2';
AppRegistry.registerComponent('MyPage1', () => MyPage1);
AppRegistry.registerComponent('MyPage2', () => MyPage2);
++/code>++/pre>
In the android project :
++pre>++code>ReactRootView mReactRootView = new ReactRootView(this);
ReactRootView mReactRootView2 = new ReactRootView(this);
mReactRootView.startReactApplication(mReactInstanceManager, "MyPage1", null);
mReactRootView2.startReactApplication(mReactInstanceManager, "MyPage2", null);
++/code>++/pre>
In the ios project :
++pre>++code>self.rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"MyPage1" initialProperties:nil launchOptions:nil ];
self.rootView2 = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"MyPage2" initialProperties:nil launchOptions:nil ];
++/code>++/pre>
You will need to create new page with the same header at some point of the application, maybe in a modal, to call some API and existing native services. It will be a lot easer to do if you can ask for help to understand how this is done.
If your aren't the initial developer of the application, be sure to have this resource available.