React Native: Is It Worth It? (Part I)

Andy Dyer
ProAndroidDev
Published in
7 min readDec 2, 2017

--

Intro

When new technologies start gaining momentum in the Android community, the pragmatic (or lazy) among us eventually have to ask ourselves, “Is it worth it?” After the initial arrival and departure of the hype train, some of these become trusted tools we use in almost every app. Think RxJava and Dagger.

React Native may be on its way to earning a place in the same club. Once we get past the fact that JavaScript on Android and HTML in JavaScript seem pretty damn weird at first, there’s a lot to like. Seeing your changes on a device almost instantly is a love-at-first-sight kind of thing. Like Instant Run, only more instant. And rethinking your app architecture as a series of actions, state changes, and UI render phases can eliminate a surprising number of silly bugs.

A dive into every new technology starts with the flashy “type these commands and run your ‘Hello World’ app” tutorial. This is not that kind of post. Instead, I’ll recap my experience digging into React Native for real world use. From integrating RN code into an existing Java/Kotlin app to dealing with the kind of problems they never mention in the README, I’ll cover what you need to know to decide if React Native is really worth your time.

Why React Native?

As I see it, there are four reasons why you might want to consider using React Native:

  1. Fast Iteration — Hot reloading enables fast iteration as changes show up on an emulator instantly.
  2. Cross Platform — Much of the code can be shared between Android and iOS.
  3. Dynamic Code Updates — React Native is unique it its ability to push updates to devices without requiring an app release.
  4. Learning Something New — Web developers want to build mobile apps and mobile developers want to learn about web development. And some (like myself), want to ease back into web development after focusing on mobile for the last several years.

React Architecture

These days, most large Android apps either adhere to the MVP or MVVM architecture. Models, state changes, and UI logic are kept separated. But how and when the UI is updated is largely up to us to decide on a case by case basis. With React, these decisions have been made for us. Our UI is driven by state changes and that’s pretty much it. State is a first class citizen and the UI is rendered anytime it changes. By breaking the UI into components with a unidirectional data flow, code is organized into small, reusable building blocks following a well defined pattern:

React Architecture

Sample App

Let’s look at a small sample app to help visualize how things fit together:

Run It!

At the top of the file, we import the components we want to reference in this file. First we import some React classes, followed by the React Native classes we’ll be using.

Below that, we declare a SampleApp component that extends React’s Component class. Our constructor takes a map of properties passed from the parent, and calls through to super(). Then, we initialize our state map with an empty string for the greeting we’ll be displaying.

If nothing else, most components will have a render() method. Here, we use a hybrid of HTML and Javascript known as JSX to return the view we want to render. In this case, we’re rendering a text input and a greeting based on the value of this.state.greeting, or nothing if no text has been entered.

Any changes to the state map cause the render() method to run again. As we type in the text box, the greeting text is updated, which instantly updates the greeting text on screen. State management in React is almost as complicated of a topic as React itself, so I won’t delve into that here. Redux is currently the preferred state management container for large apps, but most intro tutorials will caution against using it until you get far enough with properties and the state map to encounter some of the problems Redux solves.

Below our SampleApp component, we define the stylesheet classes you see applied in the render() method. Most of the style attributes are the same CSS you’d use for the web (after converting from kebab-case to camel case). Dimensions specified here translate to dp on Android and logical pixels on iOS. Finally, we register our component with React Native, providing a name we can use to load it on the native side.

Integration with Existing Apps

Now that we have a basic understanding of how React apps are architected and how React Native brings that to Android, let’s talk about my experience integrating React Native into an existing app. I won’t cover setting up a new all React Native app from scratch, as there are tutorials and generators that make this pretty straightforward.

I started by following the Integration with Existing Apps tutorial on the React Native documentation site. In a nutshell, this involves running some yarn commands to pull down React Native dependencies, making a few build.gradle changes, and adding an Activity to load a “Hello World” Javascript file. There are several steps, but they’re pretty easy to follow. Then we run yarn start to bundle the Javascript (a step replaced by a pre-build task for release builds) and run our app. Simple enough, right?

Wrong. When I tried this using v0.45, I encountered my first problem. At that time, React Native was using OkHttp v3.4 and our app was using a newer version. Between those versions, there were several breaking changes that meant we could not simply force a newer version of the library. For those of you playing blog post BINGO, there’s your first Square library mention.

But, it’s open source. Surely someone else has had the problem and solved it, right? Correct! There was even a pull request open to update React Native to v3.8. Let’s take a look at a few key parts of the discussion:

So, how might we proceed?

FOUR MONTHS after it was originally opened, the PR was merged. Problem solved? Nope!

A couple weeks later, OkHttp v3.8 had an issue of its own that required React Native to downgrade to v3.6! What a rollercoaster!

I’ve since learned that there a few different ways to integrate React Native dependencies into an existing app:

  1. Add dependencies directly to your app — Unfortunately, this won’t work if your Android and iOS apps are in separate repos. Even if you’re cutting-edge enough to be using a monorepo, this approach means every developer on your team has to know about the React Native portion of your codebase.
  2. Package dependencies in a separate library — This seems to be the obvious alternative to the first option until you realize that React Native is distributed via NPM rather than standard native mechanisms like Maven/Gradle/Cocoa Pods. If you want to go this route, you have to package React Native itself and any libraries with native code manually along with your own React Native features.
  3. Electrode Native from WalmartLabs — I’ve spent some time with this and it seems to be the best option. The documentation is very thorough but it takes time and patience to set things up. I plan to share more about my experience soon, but suffice it to say it solves the issues with the previous two approaches in a way that should scale for large distributed teams (because Walmart).

The OSS License Drama

On top of the integration challenges, Facebook also recently clarified their position regarding the open source license for React Native. I’m no lawyer, but the license for Facebook open source projects makes them free to use with the stipulation that if you sue them for patent infringement, you lose the license. Does your company do anything that Facebook might do in the future? If so, this is essentially the old mobster line updated for the digital world:

Nice app you got there. It would be a shame if anything…happened to it.

There were plenty of rants online about this, while others don’t seem too concerned judging by conversations I had at a recent React Meetup in Berlin. The fallout even led to companies like WordPress ditching a nearly finished React rewrite for something less legally volatile.

Either way, this brings us to our first consideration when deciding to use React Native:

It’s a big dependency and may limit your ability to upgrade other libraries.

Large companies open sourcing things are more focused on their own needs (and rightly so) than the community of developers using their projects. Popular libraries also serve as a recruiting tool. Solving problems for others is a bonus.

Conclusion

In the first part of this two-part series, we saw that despite its popularity, React Native can be challenging to integrate with an existing app. And while its OSS license has cause some concern, the platform continues to enjoy rapid growth.

In Part II, we’ll examine the development experience, cross platform code sharing, and dynamic updates. This is the part where I ask you to clappity-clap if you found this useful, etc. Thanks for reading!

Originally published at andydyer.org

--

--