A clueless look at React Native: setting it up

I’ve been using React for a a couple of years, but I was never really interested in React Native.

Part of the reason is the aversion I had towards developing mobile applications in general, before React Native was even a thing; I found it tedious, having to debug your app in dozens of different devices with different screen sizes, versions and so on, to make sure everything worked correctly.

Also a few years ago I developed an application with PhoneGap, but at the time the Android emulator was painfully slow, and when deploying the app to an actual device, everything looked and behaved differently. But that was probably just my fault 😅

Thus when React Native was out, I just continued to ignore the mobile development world and I didn’t pay too much attention to it.

However, in the past few months I started looking more and more into it, and discovered the vast amount of tools and libraries that greatly simplify and speed up development.

Above all create-react-native-app for quickly setting up a project with (almost) zero configuration, Expo for deploying and publishing the application without having to package it for iOS and Android yourself…

So I had to give it a try and to start creating something with it.

NOTE: I must say here that I only focus on Android development, as I don’t have an iPhone or iPad I could use for testing, or even just a Mac, neither I really care much.

NOTE: I must also say that I’m using Windows 10. With a Mac you would probably find different issues, or maybe no issue at all.

Connecting to a real device

First thing I did was to follow the instructions of create-react-native-app to setup a new project.

I downloaded the Expo app on my phone, executed

yarn start

on the terminal, everything looked correct.

Then I used the QR Code to open the app… boom, something went wrong.

After some digging, I found out this issue, apparently, the error comes from having multiple network interfaces, mainly those created by Virtualbox, which have a higher priority over the one actually used to connect to the internet.

Actually, I should have read the documentation more carefully, as it’s even stated in the User Guide:

In some cases, this is less than ideal. This might be the case if you need to run your project inside of a virtual machine and you have to access the packager via a different IP address than the one which prints by default. In order to override the IP address or hostname that is detected by Create React Native App, you can specify your own hostname via the REACT_NATIVE_PACKAGER_HOSTNAME environment variable

On Windows, they suggest using

set REACT_NATIVE_PACKAGER_HOSTNAME='my-custom-ip-address-or-hostname'

Where my-custom-ip-address-or-hostname can be found by executing ipconfig,taking note of the IPV4 address of the correct network interface, “Wi-Fi” in my case.

After doing that, you should be able to execute yarn start again and be good to go.

No. Still not working for me. Something went wrong, again!

After even more digging, I found this useful comment, which states that, when using Git Bash for Windows, the actual command is

export REACT_NATIVE_PACKAGER_HOSTNAME='my-custom-ip-address-or-hostname'

And actually, you can verify if you are using the correct IP by checking the CLI output printed just after the QR Code

Your app is now running at URL: exp://192.168.1.3:19000

That is my local IP! Indeed, I was now able to successfully view the app on my phone.

NOTE: if that doesn’t work, make sure that the ports 19000 and 19001 aren’t blocked by a firewall.

Connecting to an emulator

Emulators are cool, now I even prefer them over the actual device for a few reasons:

  • No battery consumption.
  • They are fast. In development mode, they are even faster than the actual device, at least in my limited experience, having an oldish Sony Xperia Z1 compact as an actual device.
  • Being able to test on multiple devices and Android versions without having to buy dozens of real devices.
  • No network related issues.

Even though you can probably fix some of these by connecting your actual phone via USB.

Setting up an emulator was relatively straightforward. I followed https://docs.expo.io/versions/latest/workflow/android-studio-emulator

After downloading and installing Android Studio, an important thing to do is adding adb to the PATH environment variable.

As one would expect, the article above doesn’t refer to Windows in any way. Still, you can figure out how to add to the PATH in Windows with a simple google search (if you even need to look it up).

However adding the SDK Location to the PATH didn’t work, as the adb command was nowhere to be found, closing and reopening the terminal didn’t help.

More googling, and I found out that the adb executable is in the platform-tools subdirectory, this means that, in my case, I had to add “C:\Users\maluen\AppData\Local\Android\Sdk\platform-tools\” to the PATH.

The other important step is creating the virtual device (the emulator) with the AVD Manager of Android Studio. The Expo guide states it can be found in “Tools -> Android -> AVD Manager”.

I didn’t have it. More googling and I figured out how to make it appear, I had to create a project (never did that before), then I had to press “Ctrl + Shift+ a” and type “AVD Manager” in the search box.

I then created the virtual device without issues, and now I can even see the AVD Manager under “Tools -> Android”, don’t ask me why.

Next, I was ready and excited to run the app on the emulator, so I just pressed ‘a’ on the terminal and hoped for the best. Obviously, it wasn’t working, you actually have to launch the emulator yourself.

You can check which devices are attached and ready to use, by executing adb devices If you don’t see the emulator there, then you did something wrong.

A note about speed

I started messing around with CRNA (create-react-native-app) on a real device, by calling setState to trigger a re-render; to my surprise, it was painfully slow, like every state update had a 200–500 ms delay.

In the beginning, I thought my code was to blame, but I wasn’t really doing anything special.

I also knew that react-native wasn’t to blame, since thousands of developers and even big companies use it in production nowadays.

Some research led me to the development mode section of the Expo docs:

This comes at a cost: your app runs slower in development mode. You can toggle it on and off from XDE. When you switch it, just close and re-open your app for the change to take effect. Any time you are testing the performance of your app, be sure to disable development mode.

Indeed, I rebuilt the app in production mode and it was blazing fast!

NOTE: I noticed that when running the same app on the emulator, it runs much faster than on the real device, almost same speed as production. This might only apply to my device or to the simple app I was running.

Hot Reloading

Honestly, I don’t trust Hot Reloading anymore. Even with regular React applications, it always ends up working inconsistently, maybe it works for simple CSS changes, but sometimes it doesn’t, in a seemingly random way.

This seems to be the case too with CRNA, you change some file, maybe just change some text, on the device you see the “Reloading” popup, but then nothing actually changed. Other times it just works.

This kind of inconsistent behavior is quite annoying during development, since if you can’t trust the tools you are using, then you don’t really know if something doesn’t work because of a bug you have introduced (a missing semicolon somewhere 😏), or just because the tool didn’t work that time.

What I noticed is that sometimes the whole app gets reloaded, you can notice this as the screen becomes blank for one or two seconds, and then the updated app appears.

When that kind of reload happens, then you can assume the whole thing was updated. Otherwise don’t.

When it doesn’t happen, I just reload the whole thing manually. Just shake your phone like a madman until you see a dropdown with several debug options. You want to press Reload.

NOTE: when using an emulator, since I can’t shake that for obvious reasons, what I do is I close the application and then I press ‘a’ in the terminal to automatically reopen the updated application.

Much more rarely, I also encountered weird React errors that seemed unrelated to my code, race conditions when building code, you name it. The important thing to note here is that they didn’t go away even with the shaky-shaky manual Reload.

In this case, I had to press ‘R’ on the CLI to restart the packager and clear cache, while also reopening the app in the device once the packager was ready.

Going further

With everything ready, the next step was to start some actual development.

The goal for my first application was to focus on something simple, that I could use to get introduced to the basic concepts of both the React Native API, Expo, handling gestures, animations and so on.

So I chose to create an Android Calculator clone, so original.

Check the next article to find out what went wrong next and how I managed to overcome issues in more clueless ways!

If you have suggestions on how to be less clueless, write them in the comment section below.