Skip to content

Instantly share code, notes, and snippets.

@almost
Last active November 17, 2022 14:05
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save almost/898a829d5197c69d29b0 to your computer and use it in GitHub Desktop.
Save almost/898a829d5197c69d29b0 to your computer and use it in GitHub Desktop.
Test React Native on the simulator and on a device without editing the code each time!

In the default React Native app scaffolding you have to edit AppDelegate.m to change where it loads the code if you want to test on your device. I use the following snippet to detect if it's being compiled for Debug or Production and for the Simulator or a device. For Production it uses a copy of the code included in the bundle, for Debug on the simualtor it loads from a server on localhost and for Debug on a device it loads from a server on a given IP address.

NOTE: You need to edit YOUR-IP-HERE and change it to the IP to load the code from when in Debug mode on a device. You could use a service like ngrok to make this work from anywhere.

  NSURL *jsCodeLocation;

  // Loading JavaScript code
  #if DEBUG
    // For Debug build load from development server. Start the server from the repository root:
    //
    // $ npm start
    #if TARGET_IPHONE_SIMULATOR
        // Run from locally running dev server
        jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
    #else
        // Run on device with code coming from dev server on PC (change the IP to your PCs IP)
        jsCodeLocation = [NSURL URLWithString:@"http://YOUR-IP-HERE:8081/index.ios.bundle"];
    #endif
  #else
    // For production load from pre-bundled file on disk. To re-generate the static bundle, run
    //
    // $ curl http://localhost:8081/index.ios.bundle -o main.jsbundle
    jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
  #endif
// My complete AppDelegate.m file
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import "RCTRootView.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
// Loading JavaScript code
#if DEBUG
// For Debug build load from development server. Start the server from the repository root:
//
// $ npm start
#if TARGET_IPHONE_SIMULATOR
// Run from locally running dev server
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
#else
// Run on device with code coming from dev server on PC (change the IP to your PCs IP)
jsCodeLocation = [NSURL URLWithString:@"http://192.168.11.57:8081/index.ios.bundle"];
#endif
#else
// For production load from pre-bundled file on disk. To re-generate the static bundle, run
//
// $ curl http://localhost:8081/index.ios.bundle -o main.jsbundle
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"activeinbox"
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
@adamterlson
Copy link

Is it possible to do a similar check from the JS side of things?

@damoonvisuals
Copy link

Thanks for this gist. It will definitely save me a lot of dev time.

@adamterlson: I used the package https://github.com/GertjanReynaert/react-native-device to detect the Simulator

@adamterlson
Copy link

@dsun412 Thank you!

@esutton
Copy link

esutton commented Feb 26, 2016

This should be the default template for react-native projects! Thank you!

I need to make a build script to set YOUR-IP-HERE

@kushal
Copy link

kushal commented May 6, 2016

agreed w/ @esutton. have you tried submitting a PR?

@maluramichael
Copy link

Now we got the auto discover feature.

@afilp
Copy link

afilp commented Sep 6, 2016

About the "auto discover" feature: Hot reloading and Live reloading does not seem to work on my v0.32. The options are not even there. Any ideas what to do? Thanks!

@nicnilov
Copy link

Note that you can run on a device using CLI without any modification to the source:

react-native run-ios --device "optional device name"

I'm not sure how long has this option been there though.

@sovichet
Copy link

sovichet commented Apr 7, 2018

The new RN (I'm using RN 54) has updated the jsCodeLocation to this
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

So I will be using this:

#if DEBUG
  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
#else
  jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif

@brzonsea
Copy link

Hi, I'm tried this out but got this error.

error: bundling failed: NotFoundError: Cannot find entry file index.ios.js in any of the roots:

I think this is because I'm using React Native v0.54, and now the index.ios and index.android are deprecated and combined into a single index.js file. (Since RN v.0.49 I believe?)

So I changed the
jsCodeLocation = [NSURL URLWithString:@"http://YOUR-IP-HERE:8081/index.ios.bundle"];
to
jsCodeLocation = [NSURL URLWithString:@"http://YOUR-IP-HERE:8081/index.bundle"];
and now it seems to work.

@scientist1642
Copy link

As @sovichet pointed out it just works fine for me now too.

 #ifdef DEBUG
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  #else
    jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
 #endif

However to make it work on emulator, I had to add the following to your info.plist again (as I removed it during your last release)

<dict>
  <key>NSExceptionDomains</key>
  <dict>
     <key>localhost</key>
     <dict>
       <key>NSExceptionAllowsInsecureHTTPLoads</key>
       <true/>
     </dict>
   </dict>
</dict>

@NilsonLima
Copy link

NilsonLima commented Jul 3, 2018

@sovichet solution worked for me. It saved a lot of dev time. Thank you so much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment