There is a lot you can do with the React Native Navigator. Here, I will try to go over a few examples of what you can do with the Navigator and explain how it all works in depth.

In React Native you have two choices as of now for Navigation (only one cross platform) out of the box, as well as the ExNavigator from Exponent. We will focus on the main Navigator component as that is what most questions I have seen pop up are about, and is the cross platform navigator option. We will not talk about NavigatorIOS as it is not currently maintained by the main react native project and is only available for use on iOS. But definitely check out ExNavigator by Exponent, it is also really good.

Part 1 — Basic Scene Rendering

One thing to understand is that whatever you pass to

navigator.push

is then available in the renderScene method as a property of the route.

Let’s look at an example:

Set up your Navigator like this:

<Navigator
style={{ flex:1 }}
initialRoute={{ name: 'Main' }}
renderScene={ this.renderScene } />

Then, your renderScene method like this:

renderScene(route, navigator) {
if(route.name == 'Main') {
return <Main navigator={navigator} />
}
if(route.name == 'Home') {
return <Home navigator={navigator} />
}
},

When you are ready to push a route, you could to this:

_navigate(){
this.props.navigator.push({
name: 'Home', // Matches route.name
})
}

To call it, simply use:

<TouchableHighlight onPress={ () => this._navigate() }>
<Text>GO To View</Text>
</TouchableHighlight>

Passing Properties

What about passing properties? Let’s look at the above example and add this functionality.

We need to set up an object that we will use to pass these properties. Many people use the name passProps, but this can be whatever name you want. passProps just makes sense as it is actually passing properties. Our navigator component will stay the same. First, let’s edit our renderScene method:

renderScene(route, navigator) {
if(route.name == 'Main') {
return <Main navigator={navigator} {...route.passProps} />
}
if(route.name == 'Home') {
return <Home navigator={navigator} {...route.passProps} />
}
},

Next, our _navigate function:

_navigate(property){
this.props.navigator.push({
name: 'Home',
passProps: {
name: property
}
})
}

And finally let’s pass a property to the navigator:

<TouchableHighlight onPress={ () => this._navigate('Hello World') }>
<Text>GO To View</Text>
</TouchableHighlight>

There is a sample of the above application HERE.

When you have a large application with a lot of routes, the renderScene method we defined above will start to get very large. Next, let’s make the renderScene method more dynamic.

Remember: anything you pass into your navigator.push method will be available as a property on the route.

This means if you call:

this.props.navigator.push({
name: 'chris',
animal: 'dog',
children: 6,
state: 'Arizona'
})

All of these above properties will be available in the renderScene method as a property of the route:

renderScene(route, navigator) {
route.name === 'chris' // true
route.animal === 'cat' // false
route.children === 7 // false
route.state === 'Arizona' // true
}

This way you can do calculations based on what has been passed in:

if(route.animal == 'cat') // do something, render a certain scene or something

Part 2 — Dynamic Scene Rendering

Let’s set up a new renderScene method using another implementation:

renderScene(route, navigator) {
return React.createElement(route.component, { ...this.props, ...route.passProps, route, navigator } )
}

…this.props —spread attributes to ensure any props passed down are available as usual as this.props

…route.passProps — when pushing to a route, allows a passProps property to pass props to next to component

route — route available as a prop on the component

navigator — navigator available as a prop on the component

There is another way to render the above configuration, though we will not be using it in our example it is useful to know about as it has an easier to read syntax if you are not familiar or do not want to use React.createElement:

renderScene(route, navigator) {
let RouteComponent = route.component
return <RouteComponent navigator={navigator} {...route.passProps} />
}

or:

renderScene(route, navigator) {
return <route.component navigator={navigator} {...route.passProps} />
}

As you can see in the first dynamic example above, we are using the React.createElement function to manually create our component definition.

Below is the api for React.createElement in React Native:

ReactElement.createElement(component, [object props], [children …] )

The first argument is the component to render, the second argument is an object containing any props that need to be attached to that component, and the third argument is any children.

To use this, we will call navigator.push like this:

_navigate(name) {
this.props.navigator.push({
component: Home,
passProps: {
name: name
}
})
}

And pass the properties like this:

<TouchableHighlight onPress={ () => this._navigate('SOME NAME') }>
<Text>GO To Home</Text>
</TouchableHighlight>

The component has to be available in the scope of the view for this to work. You can either import the view into the page:

import Home from '../pathtohome'

Or create the component in the same file.

There is an example of the above configuration here.

Part 3 — Scene Configuration

You can control how the navigator renders the scene into the view with the configureScene method on the navigator. The properties available are:

PushFromRight
FloatFromRight
FloatFromLeft
FloatFromBottom
FloatFromBottomAndroid
FadeAndroid
HorizontalSwipeJump
HorizontalSwipeJumpFromRight
VerticalUpSwipeJump
VerticalDownSwipeJump

To implement this, you can set up your navigator with this additional property and attach it to a function:

<Navigator
configureScene={ this.configureScene }
style={{ flex:1 }}
initialRoute={{ component: Main }}
renderScene={ this.renderScene } />

Then, set up your configureScene and pass in one of the above listed configurations:

configureScene(route, routeStack){
return Navigator.SceneConfigs.PushFromRight
}

One interesting way to use this is to check for a route property, then show a modal without having to do a lot of configuration:

configureScene(route, routeStack){
if(route.type === 'Modal') {
return Navigator.SceneConfigs.FloatFromBottom
}
return Navigator.SceneConfigs.PushFromRight
}

Now, we just need to pass the type to the navigator, and set a default type:

_navigate(name, type='Normal') {
this.props.navigator.push({
component: Home,
passProps: {
name: name
},
type: type
})
}

If no type is defined in the _navigate call, then type=’Normal’ will be the default. If anything else is passed as the second argument to _navigate, ‘Normal’ will be replaced.

And we can call the modal like this:

<TouchableHighlight 
onPress={ () => this._navigate('HELLO!!', 'Modal') }>
<Text style={ styles.buttonText }>Show Modal</Text>
</TouchableHighlight>

Tada! Here is a working example of Scene Configuration.

Part 4 — Custom Navigation Bar

You may want to have a persistent Navigation Bar in your app. To do this, you need to add another property to the Navigator component called navigationBar and pass in a <Navigator.NavigationBar /> component:

navigationBar={
<Navigator.NavigationBar
style={ styles.nav }
routeMapper={ NavigationBarRouteMapper } />
}

Then we set up the NavigationBarRouteMapper object to configure the nav bar. The NavigationBarRouteMapper takes three function arguments:

LeftButton(route, navigator, index, navState) { 
// some component or null
}
RightButton(route, navigator, index, navState) { 
// some component or null
}
Title(route, navigator, index, navState) { 
// some component or null
}

We’ve already covered the route and navigator properties, and the same properties will be available in the route and navigator properties here as they are in the renderScene method. index keeps tabs of how far into the route stack you are. index starts at 0 an goes up, so if you want to do calculations based on index you can use this.

We will check if index is zero to show or hide the back button.

We will also check to see if there is a route.onPress function passed in and show or hide a right button with a custom function and text:

var NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if(index > 0) {
return (
<TouchableHighlight
underlayColor="transparent"
onPress={() => { if (index > 0) { navigator.pop() } }}>
<Text style={ styles.leftNavButtonText }>Back</Text>
</TouchableHighlight>)
}
else { return null }
},
RightButton(route, navigator, index, navState) {
if (route.onPress) return (
<TouchableHighlight
onPress={ () => route.onPress() }>
<Text style={ styles.rightNavButtonText }>
{ route.rightText || 'Right Button' }
</Text>
</TouchableHighlight>)
},
Title(route, navigator, index, navState) {
return <Text style={ styles.title }>MY APP TITLE</Text>
}
};

Next, let’s set up our .push configuration, create our onPress and pass the onPress method as a property of the route:

onPress() {
alert("YO FROM RIGHT BUTTON")
} gotoNext() {
this.props.navigator.push({
component: Two,
passProps: {
id: 'MY ID',
},
onPress: this.onPress,
rightText: 'ALERT!'
})
}

Here is what this looks like:

Here is a working example of the navigationBar.

Part 5 — Navigator Methods

So far, we have been using the push method of the navigator:

this.props.navigator.push({ 
component: SomeComponent
})

But, there are quite a few other methods as well:

getCurrentRoutes() - returns the current list of routes
jumpBack() - Jump backward without unmounting the current scene
jumpForward() - Jump forward to the next scene in the route stack
jumpTo(route) - Transition to an existing scene without unmounting
push(route) - Navigate forward to a new scene, squashing any scenes that you couldjumpForward to
pop() - Transition back and unmount the current scene
replace(route) - Replace the current scene with a new route
replaceAtIndex(route, index) - Replace a scene as specified by an index
replacePrevious(route) - Replace the previous scene
resetTo(route) - Navigate to a new scene and reset route stack
immediatelyResetRouteStack(routeStack) - Reset every scene with an array of routes
popToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmounted
popToTop() - Pop to the first scene in the stack, unmounting every other scene

Here is how you would implement some of these other methods:

this.props.navigator.replace({ 
component: SomeComponent
})
this.props.navigator.pop()
this.props.navigator.popToTop()
this.props.navigator.resetTo({ 
component: SomeComponent
})

I’ve set up a project here with these methods implemented.

React Native may be undergoing a future change in the navigation, as there is a proposal to replace the api and functionality. In that case, I will try to do another tutorial on the new navigator functionality in the future if it is released!

My Name is Nader Dabit. I am a developer at School Statuswhere we help educators make smart instructional decisions by providing all their data in one place. Check us out @schoolstatusapp.

If you like React Native, checkout out our podcast — React Native Radio onDevchat.tv

[转] React Native Navigator — Navigating Like A Pro in React Native的更多相关文章

  1. 什么是 Native、Web App、Hybrid、React Native 和 Weex?(转载)

    什么是 Native.Web App.Hybrid.React Native 和 Weex?   来源:zwwill_木羽 segmentfault.com/a/1190000011154120 一句 ...

  2. Wait… What Happens When my React Native Application Starts? — An In-depth Look Inside React Native

    Discover how React Native functions internally, and what it does for you without you knowing it. Dis ...

  3. 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目

    前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...

  4. React与ES6(四)ES6如何处理React mixins

    React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...

  5. react看这篇就够了(react+webpack+redux+reactRouter+sass)

    本帖将对一下内容进行分享: 1.webpack环境搭建: 2.如何使用react-router: 3.引入sass预编译: 4.react 性能优化方案: 5.redux结合react使用: 6.fe ...

  6. 玩转 React 【第03期】:邂逅 React 组件

    上期回顾 前文我们讲解了 React 模板 JSX,接着我们继续来看看 React 组件又是如何工作的呢? 组件化开发到了今天已经是大家的共识,在 React 中,组件同样也是组成我们整个项目的基本单 ...

  7. [React] Use the Fragment Short Syntax in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is upgrading to Ba ...

  8. react 16.8版本新特性以及对react开发的影响

    Facebook团队对社区上的MVC框架都不太满意的情况下,开发了一套开源的前端框架react,于2013年发布第一个版本. react最开始倡导函数式编程,使用function以及内部方法React ...

  9. React Native常用组件之TabBarIOS、TabBarIOS.Item组件、Navigator组件、NavigatorIOS组件、React Navigation第三方

    以下内容为老版本React Native,faceBook已经有了新的导航组件,请移步其他博客参考>>[我是传送门] 参考资料:React Navigation  react-native ...

随机推荐

  1. Form表单中的三种查询方法

    1.使用:parameter.G_query_find参数: IF (NAME_IN('PO_HEADERS.PO_HEADER_ID') IS NOT NULL) THEN    :paramete ...

  2. Eclipse问题解决方案,不断更新

    执行“software update”时出现:Error retrieving "feature.xml"... 执行“software update”时出现:Error retr ...

  3. Charles抓Https的包

    1: 手机上打开这个地址, 安装文件. http://www.charlesproxy.com/getssl 2:保证手机与电脑在同一个网段 3:按住alt再点击wifi, 显示出当前电脑的ip地址. ...

  4. Enum 枚举

    一: 1. foreach (int val in Enum.GetValues(typeof(AppEnum.HarbourStatus))) { ddlStatus.Items.Add(new L ...

  5. powershell学习

    PowerShell 调试器 在开始运行处,输入powershell ISE回车即可 PowerShell 与操作系统版本 powershell在windows server 2008上自带,但最好在 ...

  6. Spark + Mesos 注意事项

    在使用spark-submit的过程中,需要注意 spark-defaults.conf Spark-defaults.conf的作用范围要搞清楚,编辑driver所在机器上的spark-defaul ...

  7. HW机试字符串压缩java(1)

    package huawei; public class StringZip { public static String stringZip(String a) { String ans =&quo ...

  8. uvalive 7331 Hovering Hornet 半平面交+概率期望

    题意:一个骰子在一个人正方形内,蜜蜂在任意一个位置可以出现,问看到点数的期望. 思路:半平面交+概率期望 #include<cstdio> #include<cstring> ...

  9. POJ2407–Relatives(欧拉函数)

    题目大意 给定一个正整数n,要求你求出所有小于n的正整数当中与n互质的数的个数 题解 欧拉函数模板题~~~因为n过大~~~所以直接用公式求 代码: #include<iostream> # ...

  10. tomcat运行问题解决方法

    早上过来遇到一个非常奇怪的问题,运行一个新的项目,运行环境都没问题,可是在调试的时候,总是出错. 错误代码: log4j:WARN No appenders could be found for lo ...