Automated IP Configuration for React Native Development


There are three types of application builds we need to do for React Native development: debug, debug on target device, and production. As React Native is currently set up, you need to edit your AppDelegate.m file to switch between these three.
If you have done any kind of development beyond running your app in an iOS simulator, you are familiar with this bit of the AppDelegate.m file for your project:


The localhost URL in “OPTION 1” is fine until you try to debug your application on a physical device. Then the URL has to be changed to the IP address of your development host machine before you build and run. Depending on the version of React Native you are using in your project, you may have to change that URL back to localhost to debug in the simulator again.
When you want to build a production version of your app, you need to change your product scheme to Production and edit your AppDelegate.m to enable OPTION 2.

It’s a bit messier when you have a laptop and use it while out and about so it’s IP address changes dynamically. Similarly, if you are working with a team of people, each of them have systems with differing IP addresses and everyone editing the AppDelegate.m file is sure to cause conflicts and hassles.

Surely there is a better way.

Andrew Phillipo posted his solution on GitHub here: The solution presented here is Inspired by his effort, and should automate and fix this issue with Native React.

In this gist, I have made a couple of improvements to Andrew’s Run Script:

First, there was only one PLISTCMD in his version, the one on line 5 in my version. When I tried to do a build with his Run Script, I got an error, “SERVER_IP” does not exist. In my version, I first attempt to ADD the SERVER_IP value (lines 3-4) and then attempt to set the SERVER_IP value (lines 5-6) in the project’s Info.plist file. Note the “|| true” at the end of lines 4 and 6 – this prevents the script from aborting on the failure of either PListBuddy command. The command line to determine your development machine’s current IP is within the $() on lines 3 and 5 – you can copy and paste this into a terminal to verify it works:

$ ifconfig | grep inet\ | tail -1 | cut -d " " -f 2

Second, I replaced the entire OPTION 1 vs OPTION 2 logic in AppDelegate.m with preprocessor directives to generate the proper option based upon your actual IP address. See this (second) gist:

Third, I fixed the logic in RTWebSocketExecutor.m in React Native to use the IP address we set in the Run Script. The code for setting up the WebSocket is buried in the React Native core source, and it is hardcoded to localhost:8081. This breaks debugging in chrome while executing on a physical device. My fix solves this issue. See this (third) gist:

Step by step instructions

Until the changes are made to React Native, you can follow these instructions to fix your projects to benefit from these proposed changes.


We will be editing the two files indicated on the left. We will be adding a Run Script in the Build Phases.

Step 1: Add Run Script

Click on the plus sign indicated in the screenshot above. Select “New Run Script Phase” from the popup menu.


The Run Script appears at the end of the Build Phase items list:


Click on the arrow to open it.


In the code block, we’re going to copy from the first gist I presented and paste it verbatim.


Step 2: Edit AppDelegate.m

For your convenience, the code to add to AppDelegate.m is in the second gist above.


Note: I used #if 0 … #endif to remove the original code. I left it in the source file for reference.

Also note the #warning for DEBUG DEVICE is hit – this is because I have selected my iPhone as the build target.
If I choose one of the simulators as target, the #warning for DEBUG SIMULATOR is hit:


To build a production version, I select my phone as target again and then I select Product -> Scheme -> Edit Scheme:


On the dialog that pops up, select Run on the left and set Build Configuration to Release:


In AppDelegate.m, the #warning for PRODUCTION DEVICE is hit.


Step 3: Fix the hardcoded URL in RCTWebSocketExecutor.m


Note that I commented out the original return statement and get the proper IP from the plist file, similar logic as was added to AppDelegate.m. The code for this init function is in the third gist above.


These trivial changes should improve your workflow when using React Native. It is especially effective if you develop on more than one machine or are part of a team. You will no longer be required to frequently edit the AppDelegate.m file for the three build scenarios. The number of merge conflicts you experience should be fewer since this file won’t be edited to contain per-user custom IP addresses.

If you like this work and want to see it become part of React Native, let the team know by commenting on the issue here:

* * *

Image “There’s no place like” at beginning of article via Torley under cc license.

  • Check out my tweak at:

    Fixed an issue where VirtualBox network interface IP was being picked up (first `inet` match is used starting from the bottom). Clipping the `ifconfig` output to 30 lines before filtering makes sure the correct interface is matched (for me anyway). You may need to tweak the number but the assumption is that the actual interface will appear before any added VirtualBox ones.

  • Lane Rettig

    Thanks for the great walkthrough. Even after following all of these steps, you can still get the “Unable to connect to development server” error because of App Transport Security (ATS) in iOS9: this happened to me. Cf. You should mention it here too!

    • Mike Schwartz

      I think the later react-cli versions set up ATS to work.

      When did you run react-cli to create your project? What version?

      • Lane Rettig

        Originally, last November and it looks like it may have been react-native-cli version 0.1.7. But I can’t be the only user running into this issue with a (barely) older codebase! 🙂

  • Cool, thank you. This article helped me!

  • dotan nahum

    Bumped into this article just now, check this out which implements a similar approach with an automated tool.

  • Ruslan Alekseyev

    Thank you! you did Great Job

  • jazzdle

    @mschwartzjs that was the only solution that worked for me. Thank you so much!!!

Like What You See?

Got any questions?