React Native at Classcraft
We had to carefully find a way to introduce React Native bit-by-bit into the existing native application.
Introducing React Native
So, to minimize the maintenance cost and to improve the development cycle we looked into React Native. Unfortunately, we didn’t have the bandwidth to discard our native apps and redo everything with React Native.
In order to achieve that, we tackled this one step at the time, as this timeline shows. So, we had to carefully find a way to introduce React Native bit-by-bit into the existing native application, without wasting our resources on unwanted or unnoticed refactors but also while getting traction on the bugs and features planning.
Summary of Classcraft's Mobile App timeline
- March 2014, initial commit.
- Sep 2016, both repos got merged into one with the first line of React Native.
- Spring & Summer 2017, a lot of screens got rewritten as React Native views.
- June 2017, I joined the team. 🎉
- Fall 2017, the core of the application became a React Native app hosting jointly React and native views.
First Contact Between Classcraft’s App and React Native
Our initial goal was to gradually introduce React Native into an existing native application. We kept our existing structure, but some views get refactored into React Native views, and they were mounted by the
UIViewController on iOS or a
Fragment on Android (If you attempt a similar approach, you can refer to Integration with Existing Apps docs).
Here is a high-level overview of what was the structure of the app was after the first phase integration — remember that at this phase our React Native views were only meant to replace a
It could be an entire view that got rewritten or even small components like the badge we’re using in the messaging section.
Here is the native view we’re still using for the messages:
Noticed those green notification badges?
Those are, in fact, a React Native view that’s shown on each row by the native controller. This component is meant to receive some props from the native controller and then gather the information and display a badge, if necessary.
Then with this implementation, we can integrate this component into our both platform.
We were happy with this solution, and it improved our bandwidth since we didn’t have to replicate all the logic on each platform. But still, we had to tweaks native to declare and display our React Native views or with full React Native views, we have to declare some
Fragment to host it and pass the required props. In short, it was a success, but not enough, the second phase will talk about this in deep.
The Second Phase
After successfully introducing React Native into existing apps, our goal was to switch from a native container to a React Native container, which use react-navigation to display React Native and native views seamlessly. With this structure, we’ll be able to ship feature faster as we won’t have to touch any native code and it could be done by any web wizards.
So we made the switch following the docs about Native UI Components (iOS / Android). But we end up coding our own solution to host
Fragment instead of
Layout. With this solution, we leverage our legacy views into a new app structure without having to refactor it (well actually we had to handle the navigation bar with react-navigation), but that was not a tricky part. I may write a technical blog post about this strategy to display directly a
Fragment, just ping me if you’re interested.
We still have our native application “container”, but it’s only used to launch the React Native app and to handle the sign in/up process. Even the deep linking — except for login from third parties — is a passthrough handled by react-navigation.
Following this, the native side still handles data subscriptions, but our new React Native screens are handling their own subscriptions.
Also, translations are now loaded by React Native and then sent through the bridge to the native side. At the moment, the native can’t communicate synchronously with React Native, so we send the whole dictionary of terms to the native.
Except for these points, everything stays pretty much the same on the native side after the second phase. Now we’re slowly phasing out remaining native views!
What's Next for Mobile at Classcraft
Still speaking for myself, I may have an eye on ReasonML to leverage the typing and to keep up the functional paradigm, who knows where this is going.
We had some trouble with the integration of Meteor into React Native. Actually, we use react-native-meteor, and unfortunately, this is not the real implementation of Meteor, the core got rewritten, and it’s hard keeping the beat with Meteor (we’re actually the primary maintainer of this open-source lib). We encountered many not so funny issues, which I wrote about some of them here. Hopefully, we’ll have some time soon to dig into projects like Meteor Client Bundler, which sounds great for our case and to improve the sharing between our mobile and web applications.
We’re also excited about the state of React Native in 2018, especially with all the changes that Fabric will bring.
Have you experienced any integration of React Native into an existing app or used Meteor with React Native? What’s your experience so far?