Sunny

React Native at Grain

Last year, I joined Grain, an online food company, as a software engineer to work on mobile apps using React Native. During this one year, our code base grew by over a thousand commits. We shipped a lot of product features and I grew a love-hate relationship with React Native. Here are my thoughts and hopes about React Native and its future.

TLDR;

Many big companies don’t use React Native for variety of technical and organizational issues. But we at Grain love using it, for good reasons.

Grain mobile apps stack

Using React Native, we developed and maintained two mobile apps — one for customers and one to facilitate backend operations. This is the tech stack for both apps.

Grain Mobile apps stack

What we love about React Native

Javascript & React

I started off knowing nothing about iOS or Android apps. I tried learning. But the initial setup and the learning process took a long time and I soon lost interest. React Native eliminated the friction to get started and helped me develop mobile apps quickly without worrying much about platform and tools. Building apps with React made it easy for me to adopt React Native. Also, the strong community around Javascript and React kept me going.

Before Grain, I built several products for early-stage startups with React and React Native. Over 2 years, I learned about iOS and Android platforms through my experience dealing with React Native. Later, I was able to write native modules and use them in production at Grain.

It is easy for any developer to adapt to React or React Native. This encouraged me to onboard our web developers onto mobile codebase. Once onboarded, they started fixing things very quickly by sending PRs. As most of our developers are already familiar with Javascript, it also helped us understand and reuse business logic from other clients.

Great Developer Experience (with code-sharing, hot reloading)

I enjoy working with React Native because it boosts my productivity. Unlike other hybrid app development frameworks, it also renders native components. This makes it super easy to write reusable code for both iOS and Android without compromising on basic performance. It’s easy even to separate the code based on the platform and maintain them within the same codebase using platform specific components.

Mobile development is hard as it’s time-consuming. React Native solves this problem with hot reloading. Instant feedback on every small change on the app saves a lot of time and resources.

Because it’s mostly Javascript and React, I had many other tools (react & redux devtools) to improve developer experience with better debugging and monitoring. It also helped me write quality code with speed.

Some painful memories

Upgrading React Native

We were still using React Native 0.27 until April 2018 because there was no active developer working on the Grain app. One of my first tasks at Grain was to upgrade the app to the latest version (which was 0.55 at that point). As there was no reliable way to do it, this upgrade was a painful experience. Also, there were many breaking changes, like metro blunder, to get to the latest version.

We tried 2 strategies:

  1. To use react-native-git-upgrade and fix stuff
  2. To manually change files using ncuillery/rn-diff and try upgrading

Nothing worked.

I took the last resort and created a new app with the latest version, updated all the dependencies, recreated old deployment setup and ported over all of the React/Javascript code.

Linking native modules

Another common issue was linking native modules with the react-native link which used to be the rnpm link. It was unreliable. This was particularly hard on iOS because we always had missing search paths errors when linking a module. Sometimes the app would run well in debug mode but fail in release modes.

Workarounds that worked for others often didn’t work for us. We ended up linking our native modules manually and fixed Header/Framework search paths issues and maintained the fixes separately.

This made it difficult for us to decide what’s the right one to use or if we should build one on our own. That’s why I always thought the React Native team should maintain some commonly used native modules like,

  • Video
  • Internationalisation
  • Navigation

Mobile OS’s and SDK’s get updated very regularly with new versions released every year and all of these new features only come with latest SDK’s (modules) which are not getting updated regularly (understand that open source contributors are busy). If React Native core team owns some of these modules and dedicate resources it will remove a lot of these pain points for extensive users.

Platform specific updates

React Native has always kept us updated with new features from React, this helped us in shipping good experiences for our users by leveraging these new features (context API, lazy, memo, hooks etc…). This is precisely what we missed on the platform side, eg. supporting new Xcode build system, designing for the iPhone X (SafeAreaView). Sometimes I figured things out by making mistakes, like upgrading to the latest macOS and then knowing that few things don’t work. We waited for the community to fix/update these breaking changes and at times we wrote our own components/modules to handle these exceptions. Some of these updates came in slightly late but an active blog about when to upgrade and more from the core team would’ve definitely helped us to be more cautious. Again, not blaming anyone but these are some basic expectations for any mobile developer.

Performance

We were quite happy with how our apps worked on iOS. They worked fine, w.r.t animations and were also using a limited amount of device resources. On the other hand, we had a few performance issues on Android which were caused by various reasons — some of which we fixed in a hackish way and some are just left out. Even down to Javascript, few React Native components worked fine on iOS but failed to render on Android and used to throw Layout errors.

Few critical Android issues we faced were,

  • Layout Errors and Type Errors like this and this
  • Memory leak issues which made app junky
  • Flatlist with images performance

The same code used to work fine on iOS, but Android used to have regular issues like this which took additional time to debug and fix. Some of these issues are mistakes by developer (me) but the error messages gave no right directions to fix. We know the core team is aware of some of the other issues and are constantly working on to fix them.

Finally, a few more things that could have improved our experience earlier on are clear documentations on developing with React Native, useful troubleshooting/debugging tools, and optimistic updates. Lot of things get quickly deprecated in React world and it takes time for us to get out of dependency hell that gets created because of these deprications. Error messages are still cryptic, which we think can be more straightforward and useful. However, the huge red screens and yellow alerts helped us to some extent.

Enough of the ranting, time to show some love.

Why we still love React Native

While dealing with our own issues and building products, we are always hopeful and looking forward to improvements in the framework. This always kept us curious with what’s happening in the community and we have been following the recent activities especially from the day Christoph started this little movement to make React Native great again.

We really appreciate your efforts to understand developer experiences and were super happy that you started addressing most of them with project Lean Core.

Also, the community’s involvement is really inspiring. Big thanks to every one who’re spending loads of time perfecting this magic tool, you guys are awesome. All this work improves the developer experience and solves some of our (and many) problems which we deal with React Native on a daily basis. The work around new architecture (Fabric) and Turbo Modules is keeping us excited about the future of React Native. We can’t wait to see all of this in action.

What’s next at Grain?

React Native helped many folks to build careers in mobile app development and also helped countless startups to build quality apps with less time and more productivity. We enjoyed using it and we can see how this framework is starting a revolution. This work, support and plans for React Native from core team and community will definitely improve in many areas, which we struggled with along the way. With this hope, we are confident in React Native and would continue to invest in it at Grain.

In the coming weeks, we’re upgrading both of our apps to version 0.59+ and rewriting apps to support our new expansion plans.

If this is something that excites you, please write to us at tech@grain.com.sg, we are looking for one senior front-end engineer to join us and build some cool stuff. We’re also hiring for mutiple positions, please take a look of other openings here.

👋🏻