Running Your React Native Expo App on a Device with Local Backend
Tags: reactnative, rails
Published: 2020-03-28 06:29:52

*Note - I’m using Expo, a Rails backend, and testing on iPhone/iOS Simulator so this post is only based on my experience. However, the steps should work on an Android device too.*

I’ve spent the last couple of months working on a mobile app and depending on what features I’m testing, I will run it either on the iOS Simulator or my iPhone. My app has camera and image picker integration, so when I want to take actual photos when testing the latest functionality, the iPhone is more suitable for the job as nothing beats holding the device in your hand and really getting a feel for the app. Yet more often than not, it is more convenient to run the app directly on your computer using the iOS Simulator.

However, switching between the iOS Simulator and iPhone does not have to be a pain and I’ll document my best practices below. 

###Localhost and Your IP Address
**`localhost` is a network address that points to your own computer. It's useful to test a local development server.**

The URL format is:
```javascript
'http://localhost:port_number'
``` 

The Rails development server will run by default on port 3000 (`localhost:3000`). However, this will only work if your web browser is running on the same computer as the development server.

When running my Rails backend by default, it will respond on `localhost:3000`. This is fine when everything is running on the same computer and I'm using the iOS Simulator. However, as my iPhone is definitely not on my computer, this will not work on my phone. Instead, I can use my computer's IP address while making sure my iPhone and computer are all connected on the same wi-fi network, as the testing is done over wi-fi.

###Step One: Create a Separate File For URL at the Top Level
Since there are several places throughout my code that will need to hit the backend (any fetch requests to the database, etc.) I created a separate file named environment.js and saved it at the top level of my directory. This way, I only need to update one line of code if anything changes.

In environment.js, I created two variables: `HOST` and `HOST_WITH_PORT`.

`HOST` is pointing to my computer's IP address. `HOST_WITH_PORT` is the full URL using string interpolation and will be exported so it can be used in other files.

```javascript
// environment.js
const HOST = '192.168.1.7'

// make sure to export the variable so you can import it in other files
export const HOST_WITH_PORT = 'http://${HOST}:3000`;
```
###Step Two: Import URL
Then import `HOST_WITH_PORT` wherever you need it. It will look like this:

```javascript
// ExampleScreen.js
import { HOST_WITH_PORT } from '../environment';
// ...
const onButtonSubmit = () => {
  fetch(`${HOST_WITH_PORT}/examples/example`, {
    method: 'POST',
    headers: {...}
  }
}
```
###Step Three: Boot up Rails Server
When you're ready to boot up your Rails server, instead of just `rails s` in the terminal of your Rails API directory, now use **`rails s -b=0.0.0.0`**. The **`-b` option binds Rails to the specified IP**. And `-b=0.0.0.0` specifically is telling the server to bind to all incoming IP addresses. 

###Step Four: Run App in Expo on iOS Device
Once your server is up and going, you can type either `expo start`, `yarn start`, or `npm start` in the terminal of your React Native project directory. You will be prompted with a QR code along with some options on how to run the app with live reloading. 

###Potential Roadblock
These simple steps above will usually set you up to be able to run your app seamlessly on both the iOS Simulator and iOS device. However, it is not foolproof. It will only work if you don't get sandboxed in with the IP address or a router that is not your own. Certain wi-fi networks you may connect to can put you alone in a network without access to other devices on the network. 

I hope you find this helpful when testing your app and are switching between your device and Simulator. Happy coding!