Road to React Native
Until few months back, the Simpl Android and iOS apps were fully native. The Android app is written in Java and the iOS app in Swift. It was time to bring in a new feature and this time we had a different idea in mind.
Why don’t we leverage React Native to save us some time and learn a bit in the process? The new feature was small enough to do this experiment and the pros will outweigh the cons in the long run. So we went for it.
Let’s quickly go through the basics. React Native lets you build mobile apps with javascript and run it on both Android and iOS. It also offers cool stuff like Hot Reload and Over the air updates.
Getting started with a React Native app from scratch is pretty simple. Also, there are tools like Expo that make it a breeze. But we wanted to integrate it into our existing native apps. In this post, I’ll share a few things we had to figure out to make this happen. The native code samples are for Android but the concept is similar for iOS.
Repository Structure
Firstly, we wanted to figure out the repository structure for the native and React Native code. We did not want to merge the Android and iOS repositories into one. So we created a new repository for React Native code and added Android and iOS repositories as submodules.
#Add a submodule
git add submodule <repo_url>#Clone repository with submodules
git clone --recursive <repo_url>#Update submodules
git submodule update --recursive --remote
Multiple entry points into React Native
We had multiple entry points to React Native. So the next challenge was how to best organise our code such that the entry mechanism into React Native is non-intrusive. To achieve this, we created an activity called ReactScreen that creates a ReactInstanceManager and loads the ReactRootView as its content view.
Now any new activity that wants to render a React Native view can extend from ReactScreen and reuse the instance of ReactInstanceManager.
Next up, we needed a mechanism to expose multiple entry points from the React Native side. To do that, we implemented a simple router that maps the routingKey passed from native code to its corresponding React Native Component. The router looks something like this.
And our Index component just had to delegate the routing task to the router.
The key and data are passed from the native code by setting AppProperties of ReactRootView. The key is used to route to the required component and the data is sent as props for the component to be rendered.
Bundle dataBundle = new Bundle();
dataBundle.putString("userName", userName);Bundle bundle = new Bundle();
bundle.putString("routingKey", "Key1");
bundle.putBundle("data", dataBundle);reactRootView.setAppProperties(bundle);
Bundling
During development, you can use the React Native packager to serve the React Native code. But when you generate a release build of your app for uploading to the Play Store/Appstore, you have to generate and include the js bundle file to your app. You can generate the bundle by running the following.
#Androidreact-native bundle \
--entry-file index.js \
--bundle-output ./android/app/src/main/assets/main.android.bundle \
--dev false \
--platform android \
--assets-dest ./android/app/src/main/res/ \#iOSreact-native bundle \
--entry-file index.js \
--bundle-output ./ios/App/Resources/react.ios.bundle \
--dev false \
--platform ios \
These steps got us started with React Native development. In the next post, I’ll share my learnings from setting up Over the air updates and Continuous integration pipeline for the app. Until then, keep learning!