This month I started a mobile app project. Why? I'm a Web developer since 2006 and avoided getting involved in this whole "native app development" thing like the plague. I went to university from 2007 - 2011 the time where iPhones and Android got out, and most of my fellow student got into mobile while or after their studies.

They made good money, but to me it sounded horrible!

Objective-C? Who uses this?!

Java? This was the bane of my studies!

Also, the big money seemed to be exclusively in iOS apps and I hated Apple from the bottom of my heart.

So, how did I get into this mess?

I did React for two years and had the idea that doing apps with React Native couldn't be much different, so I got me a RN project in which I'm in for a month now. Now I will tell you about what I learned.

React Native iOS apps without a Mac

It is possible. There is the Expo project for example, that lets you build on their servers and you only have to write JavaScript in your apps. They give you a client, which is basically a RN runtime. It's in play store and app store, so you simply get yourself an iPhone, install the Expo client, scan a QR-code and run your app.

A slimmer version of this process exists in the form of create-react-native-app, which basically builds on Expo, but doesn't require an Expo account to get started.

Also, Expo lets you run the app in its client over the Internet via Proxies and such, CRNA only works in your local network.

What's the catch? There is always a catch!

You can only use native modules that are included in RN and Expo, but at least Expo brings you a bunch of useful extra components like Video, Audio, Notifications and GL, so probably 80% of all apps will get along with this. You can install all JavaScript modules you like, just no native ones.

What React Native does and what it doesn't

When I started the whole thing, I thought RN would be a complete developing experience, but well, I was wrong. RN helps you developing and enables you to use your JavaScript and React skills for native apps, but it won't help you to get your app in the app store. It won't even help you to get it on all the devices of your beta testers.

If you use CRNA or Expo, you get to run your app in the Expo client on any iPhone. Expo even gives you a build service, that spits out IPAs you can get into the app store, but if you don't want to rely on Expos services OR you need other native modules Expo doesn't deliver, you will probably need to build your apps on your own.

If you develop with plain RN on a Mac, you get to run your app in the Simulator or on a USB connected device, but RN will stop at the border where your app is just a regular Xcode project.

So you did your dev and now you want to build your IPA to deliver it to the test devices of your co-workers.

React Native won't sign your code, package your app or create a provisioning profile for you. These are all Apple concepts and have nothing to do with RN.

But luckily there are other tools that do exactly this for you.

I found Fastlane, which does all the heavy lifting. It has really nice error messages and covers all the things you need to do after you coded your app and tested it on your own devices. It even seems to know about RN and gives some tips on where to run fastlane init or fastlane match init and the best is, it runs completely in the shell, so you can integrate it nicely in your package.json and run npm run build:ios:beta and be done with it. No more looking into Xcode.

Problems with Create React Native App

I used CRNA to get started, it had most features I needed and it was really easy to set things up. After 5 minutes I could write my business logic in JavaScript and all was good.

To get an IPA out of it that was signed correctly, I needed to use the Expo build service, which required an Expo account. If you don't want this, you need to eject from your CRNA project into a plain RN project and build it yourself on a Mac.

Ejecting was a bit harder than I thought, especially if you do it because you want to build things yourself.

There are two options, either the ExpoKit or the regular RN eject.

The ExpoKit option still requires you to build with the Expo service, so it wasn't an option.

The RN one didn't let me keep the Expo modules I was using. This wasn't too bad, since a few of these packages were just wrappers for regular native RN modules and I found replacements for everything else. The only thing that bit me were the vector-icons . I used them all over the place, but CRNA didn't tell me they wouldn't work anymore. So everything blew up after eject. I got it fixed rather fast tho, the Expo module was just a wrapper and I could use the regular react-native-vector-icons module.

Also, it seemed that the eject didn't set all values in the .plist file correctly. I had a app.ios.js that was registering a different name than my app was called, so Xcode couldn't find it, but I found the Xcode errors good enough to fix these issues.

When to use what?

When I did this, I had the feeling that this whole React Native thing has different levels and depending on what you need, you don't have to go all-in.

Prototyping

Create React Native App is probably enough. You get all the React Native and Expo components and APIs and will create an app you can show your co-workers or customers really fast.

You even get the possibility to eject and use most of your code. You just have to replace the Expo Components and APIs with something different then, if you don't want to use ExpoKit, which requires to use the Expo build service.

No Mac for development

Expo is the way to go, you get all the features of CRNA and a build service to package your creations. It requires a (free) Expo account. Also you only can use the included native APIs and Components.

You can detach, which is the Expo version of CRNAs eject and do regular RN development from then.

Need other native APIs and/or Components

You can use CRNA and eject right after react-native init so you get a nice project structure and end up with a normal React Native project. Then you can use native modules of your liking.

For most native APIs (probably all?) there are already so called React Native bridges that you can install via npm and include in your project via linking, so you don't have to write Objective-C or Swift yourself.

You will need to set up your own build tooling tho, but Fastlane is really nice and helps you with all steps.