Building Our First React Native Application

We just launched our first React Native application for a client this week! Shout out to Dasy Labs for trusting us with their project.

The app is live on the App Store and Play Store, so you can check it out for yourself.

Overall our experience with React Native was a positive one, but there were a few bumps along the road.

Pain Points

Bumps

Community

The React Native community is growing very fast, but it is still in its infancy so things are changing rapidly.

Some of the installation instructions in community developed modules are outdated. For example, there are lots of references to React Native Package Manager (RNPM) which is now built in to the React Native CLI.

Some modules that require manual installation have outdated instructions for one platform or another (especially Android). This is a hard problem to solve, as you effectively have to deal with the churn of 3 platforms (RN, iOS, Android).

Native Modules

Most native modules can be automatically linked by React Native CLI (react-native link OR react-native link <pkg-name>). However, the few that cannot be fully automated make upgrading React Native a pain.

The cli has an upgrade option, but it is not an automatic process. The CLI will prompt you to overwrite files that have changed or look at the diff and bring in changes yourself. It would be nice if the CLI was smart enough to automatically merge some files and perhaps even use the merge tool defined in your git config.

Styling

Styling in React Native is easy once you get the hang of it, however it's not easy to bring in CSS libraries for the web.

  • First, there are no classes, no CSS files, no style tagsā€”it's all inline styles. This sounds horrible, but RN came up with a JavaScript-based concept similar to CSS stylesheets.

  • Second, elements do not inherit styles from their parents, so you can't set the font size on a parent and expect every paragraph to inherit that.

I'm sure you could bring in Bootstrap through some build step, but for this project we decided to keep it simple and not use any external frameworks.

The biggest pain point style-wise is the fact that it is difficult to style external components if they don't provide a good mechanism for doing so. In CSS you could simply write higher specificity selectors. In React Native you can't do that.

The common practice is to allow users to override individual styles. In the future I would like to see packages accept stylesheets that replace or merge with their default styles. This would aid with styling nested elements.

Code Sharing

React Native has no concept of <div>s or <span>s, which makes compatibility with web-specific components difficult. Overall a lot less code can be shared between a web app and a React Native app than I thought. Redux improves this a lot, as you can reuse your containers, actions, and reducers, but sharing components would be difficult.

Many people believe one of the benefits of React Native is that they can share code with web apps. While that's true to some extent, it's worth mentioning that React Native is great to build cross-platform mobile apps, regardless of how much code you can share with your web app.

There are two main navigation paradigms in RN.

  • Navigator, is stateful and based on the iOS navigator, but works across both platforms.

  • NavigationExperimental is stateless, so it works decently well with Redux.

I found both of the interfaces to be a bit clunky, but NavigationExperimental was workable with Redux. Once it was setup I could forget about it, but getting there was a pain.

Xcode

Editing the project in Xcode causes unrelated settings to shift around in the project file, creating large git diffs. This is more of a problem with Xcode than React Native, but it is annoying.

Launch Screen

React Native does not seem to present a solution to style the launch screen (yet), although most of the time this is just a logo or spinner so it's not a major issue.

App Icons

Again, RN does not seem to have a unified way to deal with app icons across both platforms. The less people have to go in Xcode and Android Studio, the more powerful the platform will become.

DevTools Integration

Having the good ol' familiar DevTools console is fantastic, however it would be even better if you could see network requests in the Network panel. I believe node-inspector can do this, so I hope we'll have this important debugging ability some day.

The Good

After reading the previous section you might be wondering why on Earth would we still recommend React Native. Despite the bumps, React Native is a fantastic platform to develop mobile applications.

Easy to Learn

If you know React, it will be easy to pick up React Native. A lot of the concepts and tools you use will work just fine.

Performance

Performance is phenomenal. It feels like a native app because it is a native app. It's not a web app wrapped in a web view. I worked with Ionic and Cordova in the past and RN blows them out of the water.

Errors

The errors are descriptive and interactive. You can tap on the error in the simulator or on your phone and your code editor will open to the exact line where the error occurred. This is huge.

console.error and console.warn are monkey patched to display them on the device. It's a small but nice feature.

Redux + Redux Logger

Redux and Redux Logger make it easy to reason about your application. You can reason about why things are displayed the way they are without having full access to all of DevTools.

JavaScript All the Things

Of course, the other big benefit is that you can use JavaScript, a language already familiar to most teams.

Conclusion

Our experience with React Native was great. Although it can improve in a lot of ways, it is already a production-ready technology we can advocate to our clients.

If you are looking to build a cross-platform mobile application, contact us right now to see if React Native is a good solution for you.