Getting Started with React Native Navigation V1
There are quite a few options out there for Navigation in React Native. I typically default to React Navigation (tutorial on getting started) but that’s a Javascript based routing solution. This might not work for some people and others may just prefer a native option.
When React Native was first released the only navigation solution was NavigatorIOS, but it’s no longer being maintained and it only worked on iOS. Airbnb has native navigation, but it’s still very new.
That’s where React Native Navigation comes in — it uses native navigators on iOS and Android and has an easy to use Javascript API. I’ve never used it before but thought I would share my experiences getting up and running with it.
The final code is available on Github.
This tutorial applies to V1 of React Native Navigation. If you’re using V2 the API may have changed.
Prefer Video?
Getting Started with React Native Navigation V1
Installation
To get started I’ll create a new React Native project react-native init GettingStartedReactNativeNav
. I’m then going to scaffold the application with a few screens, which you can find here.
iOS
If anything doesn’t work/make sense please check the official documentation.
Open the project in Xcode open ios/GettingStartedReactNativeNav.xcodeproj/
. Then, since this uses native libraries, you need to link the native dependencies. First right click on “Libraries” in the project navigator and click “Add files to GettingStartedReactNativeNav…”
And select ReactNativeNavigation.xcodeproj, which can be found at node_modules/react-native-navigation/ios/ReactNativeNavigation.xcodeproj.
Now in the “Build Phases” tab (visible in top navbar of Xcode) in the “Link Binary with Libraries” tab add libReactNativeNavigation.a.
Next go to the “Build Settings” tab and search for “Header Search Paths”
and add $(SRCROOT)/../node_modules/react-native-navigation/ios
. Make sure to set it as “recursive”.
Now we need to modify the AppDelegate.m.
/**
* 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 <React/RCTBundleURLProvider.h>
+ #import "RCCManager.h"
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
+ self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+ self.window.backgroundColor = [UIColor whiteColor];
+ [[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation];
- RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
- moduleName:@"GettingStartedReactNativeNav"
- initialProperties:nil
- launchOptions:launchOptions];
- rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
- self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
- UIViewController *rootViewController = [UIViewController new];
- rootViewController.view = rootView;
- self.window.rootViewController = rootViewController;
- [self.window makeKeyAndVisible];
return YES;
}
@end
Android
Open up android/settings.gradle
and add the following to it.
include ':react-native-navigation'
project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/')
Then, in android/app/build.gradle
, update the dependencies
with compile project(':react-native-navigation')
. You also want to update compileSdkVersion
and buildToolsVersion
, located in android
.
android {
compileSdkVersion 25
buildToolsVersion "25.0.1"
...
}
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+"
compile project(':react-native-navigation') // ADD DEPENDENCY
}
Next modify MainActivity.java
package com.gettingstartedreactnativenav;
- import com.facebook.react.ReactActivity;
- public class MainActivity extends ReactActivity {
- /**
- * Returns the name of the main component registered from JavaScript.
- * This is used to schedule rendering of the component.
- */
- @Override
- protected String getMainComponentName() {
- return "GettingStartedReactNativeNav";
- }
-}
+import com.reactnativenavigation.controllers.SplashActivity;
+public class MainActivity extends SplashActivity {
+
+}
We’ve also got to modify MainApplication.java.
package com.gettingstartedreactnativenav;
import android.app.Application;
-import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
+import com.reactnativenavigation.NavigationApplication;
import java.util.Arrays;
import java.util.List;
-public class MainApplication extends Application implements ReactApplication {
+public class MainApplication extends NavigationApplication {
...
}
Then add the following to the body of MainApplication.java
// ...
import javax.annotation.Nullable;
public class MainApplication extends NavigationApplication {
// ...
@Override
public boolean isDebug() {
return BuildConfig.DEBUG;
}
@Nullable
@Override
public List<ReactPackage> createAdditionalReactPackages() {
return null;
}
}
Usage
React Native Navigation changes a bit of how React Native works (as you can tell by the installation). The biggest difference is how we register the application. We no longer use AppRegistry.registerComponent
so we’ll swap out the index.ios.js and index.android.js with the following
// index.ios.js, index.android.js
import registerApp from './app/index';
registerApp();
Then in app/index.js
we’ll create our function that actually registers the application.
// app/index.js
import { Navigation } from 'react-native-navigation';
import Screen1 from './screens/Screen1';
import Screen2 from './screens/Screen2';
import Screen3 from './screens/Screen3';
import Screen4 from './screens/Screen4';
export default () => {
};
The first thing we want to do in that function is register our screens with React Native Navigation. We’ll do that via Navigation.registerComponent
.
// app/index.js
import { Navigation } from 'react-native-navigation';
import Screen1 from './screens/Screen1';
import Screen2 from './screens/Screen2';
import Screen3 from './screens/Screen3';
import Screen4 from './screens/Screen4';
export default () => {
Navigation.registerComponent('Screen1', () => Screen1);
Navigation.registerComponent('Screen2', () => Screen2);
Navigation.registerComponent('Screen3', () => Screen3);
Navigation.registerComponent('Screen4', () => Screen4);
};
With that we can use our newly registered screens with the app. We’re going to set up a tab based app in this tutorial — which we do via Navigation.startTabBasedApp
. Inside of that config we can pass a “tabs” array which represents the tabs of our application. All of the keys are pretty self explanatory so I won’t cover them. Full documentation is available here. The only thing I’ll note is that screen must align with a screen we registered previously.
Note: I’ve added a few images to the app. You can get those in the Github repo.
export default () => {
// ...
Navigation.startTabBasedApp({
tabs: [
{
label: 'One',
screen: 'Screen1',
icon: require('./images/icon1.png'),
selectedIcon: require('./images/icon1_selected.png'),
title: 'Screen One'
},
{
label: 'Two',
screen: 'Screen2',
icon: require('./images/icon2.png'),
selectedIcon: require('./images/icon2_selected.png'),
title: 'Screen Two'
}
]
});
};
That leaves you with
Navigating Between Screens
To push a new screen onto the stack is very simple. In screens that were registered with Navigation you have access to this.props.navigation
on which you simply want to “push” a new screen to it.
// app/screens/Screen1.js
// ...
class Screen extends Component {
handlePress = () => {
this.props.navigator.push({
screen: 'Screen3',
title: 'Screen 3',
});
};
render() {
return (
<Container
backgroundColor="#F44336"
onPress={this.handlePress}
/>
);
}
}
Modal
Opening a modal is as easy as pushing a new screen onto the stack.
// app/screens/Screen3.js
// ...
class Screen extends Component {
handlePress = () => {
this.props.navigator.showModal({
screen: 'Screen4',
title: 'Screen 4',
});
};
render() {
return (
<Container
backgroundColor="#067a46"
onPress={this.handlePress}
/>
);
}
}
export default Screen;
In Conclusion
I’ve just scratched the surface of React Native Navigation and I’m excited to learn more about it. There are certainly benefits to going the native route, though installation can be a pain. I’m interested to see how flexible it is and what kind of interactions we can use with it. Until next time!
Did you enjoy this tutorial? Make sure to share it and if you’re interested in seeing more be sure to sign up for my email list!
Originally published on Medium.
hello,
i am an android developer. Now i want to learn react native.
i installed node.js and npm etc. project running successfully but not showing desired output. its showing just “unable to load script from assets ‘index.android.bundle’.” please help me.