Sie sind auf Seite 1von 13

Images haven’t loaded yet.

Please exit printing, wait for images to load, and try to


How to properly navigate with React
print again.

Navigation
Shovon Follow
Feb 18, 2018 · 7 min read

Photo showing di erent navigation routes to reach a destination. By rawpixel.com on Unsplash

EDIT: When this article was written, react-navigation was version 1. There
have been many changes in it when it reached version 3. Some parts of the
article have been updated accordingly with adding few extra details.

In this article, you will learn various ways to navigate in your


application using React Navigation. I will assume that you know the
basics of React Navigation. I will show you how to properly set, access
and pass properties in different screens to make navigation easy. Make
sure you have read the official docs before starting this to get
accustomed with this library.

Preface
React Navigation is not the only contender for navigating in a mobile
application, you can also find other navigation libraries, namely React
Native Router Flux, React Native Navigation and Native Navigation.

The last two plugin are “native” navigation i.e. they are built on top of
the Android and iOS platform navigational components, unlike React
Navigation which is a JS based solution.

If you are confused whether to use a JS based solution or a native one,


maybe this post can help you (brace for a long read!).

Introduction
You can implement React Navigation both with Redux and without
Redux. Since we are starting from scratch, we will start with “without
Redux”.

We will go with building a news application. I will name it FuNA


(Futuristic News Application).

Before we begin, here’s what you need to know about React Navigation

For navigation you need a Navigator and there are three different types
of Navigator in it — StackNavigator, TabNavigator and DrawerNavigator.

As of v3, there is a new navigator named SwitchNavigator.

Whenever you register a component with any of these Navigators,


then only navigation prop is passed to the registered component.
That prop is responsible for all navigation inside the application.

Problems
I will work with blank screens and just focus on the solutions of the
following requirements —

1. Navigating to a screen

2. Navigating to nested Child screen from Parent screen

3. Navigating to nested Child screen from a different Parent screen

4. Navigating to nested Child screen from a Child screen of different


Parent

5. Accessing navigation in a Component

6. Resetting screen to first Parent screen, from a nested screen

Setup
Hers’s a prototype of the app —

App prototype

The screens will be arranged like this —

AppStackNav
|- HomeScreen
|- LoginScreen
|- SignupScreen
|- AppDrawerNav
|- NewsStackNav
| |- NewsTabNav
| | |- NewsGlobalScreen
| | |- NewsLocalScreen
| |- NewsDetailScreen
|- AccountTabNav
|- AccountProfileScreen
|- AccountSettingScreen

And, here’s what the final app will look like—


Demo application showing usage of React Navigation

Code
We will use all our examples from this repository(for react-navigation
v1). Let’s code.

. . .

Navigating to a screen —

If you have a simple StackNavigator like below,

// navigators/AppStackNav.js
const AppStackNav = StackNavigator({
Home: {
screen: Home,
navigationOptions: {
header: null
}
},
Login: {
screen: Login,
navigationOptions: {
header: null
}
}
});

Then to navigate to Login from Home  , you would simple call

this.props.navigation.navigate("Login")

Or

this.props.navigation.dispatch(
NavigationActions.navigate({ routeName: "Login" })
);

. . .

Similarly for,

• Navigating to nested Child screen from Parent screen

• Navigating to nested Child screen from a different Parent screen

• Navigating to nested Child screen from a Child screen of different


Parent

just pass the required routeName in navigate function.

this.props.navigation.navigate("routeNameOfScreenToGo")
In v1, for a successful screen change, the routeName had to be accessible in
the screen from where you were calling the navigate function i.e. we had to
make custom actions if we had to go to any specific nested/cousin screens.

In v3, navigate function itself determines how to navigate to passed


routeName.

. . .

Resetting to a screen —

Now suppose, once someone successfully logs in, you would like to
prevent them to go back to login/signup screen. Here’s how that would
be possible

// screens/Login.js

this.props.navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName:
"Dashboard" })]
})
);

Here reset ting with index: 0 would make the screen passed in
routeName as the initial screen, removing all previous screens from the
stack.

As of v3, due to introduction of SwitchNavigator we can change our


navigation setup to following —

AppSwitchNav
|- UnauthStackNav
|- HomeScreen
|- LoginScreen
|- SignupScreen
|- AppDrawerNav
|- NewsStackNav
| |- NewsTabNav
| | |- NewsGlobalScreen
| | |- NewsLocalScreen
| |- NewsDetailScreen
|- AccountTabNav
|- AccountProfileScreen
|- AccountSettingScreen

SwitchNavigator resets routes to their default state when you switch


away from UnauthStackNav to AppDrawerNav  .

. . .

Accessing navigation in a Component —

If you use a Component to render a navigator, then you have to keep in


mind to pass that navigator’s router to Component’s router and
pass the navigation prop to the Component navigation (since that
Component is not registered as any navigator, it will not receive any
navigation prop automatically).

// screens/Dashboard.js

import React, { Component } from "react";


import AppDrawerNav from "../navigators/AppDrawerNav";

export default class Dashboard extends Component {


static router = AppDrawerNav.router;

render() {
return <AppDrawerNav navigation={this.props.navigation}
/>;
}
}

. . .

Passing ans accessing data from among screens —

To pass any data in the destination screen, you can pass your data in
params  .

// screens/NewsLocal.js

this.props.navigation.navigate("NewsDetail", { topic: "React


Navigation" })
To pass data in the current screen, you can call setParams —

this.props.navigation.setParams({
key1: 'value1',
key2: 'value2',
})

To access data passed in params in the destination screen, you can


access it in props.navigation.state.params  .

You can also call getParam —

this.props.navigation.getParam('KeyToFind',
'OptionalDataToShowIfKeyNotFound')

In our case, accessing props.navigation.state.params.topic would


give React Navigation in the destination screen.

. . .

Going back from a screen to previous screen —

this.props.navigation.goBack()

. . .

Resetting screen to first Parent screen, from a nested screen —

Let’s consider a situation when someone logs out of the application. In


that case you would want them to go to Home (assumed) without
being able to go back. Here’s how you can do that.

// screens/Dashboard.js

this.props.navigation.dispatch(
NavigationActions.reset({
index: 0,
key: null,
actions: [NavigationActions.navigate({ routeName: "Home"
})]
})
)

Notice the key: null that has been added for this case. This generally
should not be required but when you are in a child screen and want to
reset to parent screen, navigator cannot identify other routes than the
routes accessible to current screen.

This means if you are in NewsGlobal and you click logout icon (in our
app), then the only available routes the navigator finds is NewsTabNav

and NewsDetail  . As of now there is no solution for this, except this


workaround key: null  .

You can read more about this issue here.

As of v3, reset is only available in StackActions  , which means you can


only call this function from a StackNavigator  .

. . .

Going back more than one screen —

Suppose if you traversed screen in this fashion ScreenA → ScreenB

→ ScreenC  , then if you want to goBack from ScreenC to ScreenA  ,


you would have to pass the key of that screen as params in goBack

this.props.navigation.goback(’keyOfTheVisitedScreenToGo’)

You can manually set key when going to a screen. So whenever you
want to go back from that screen, you have to pass that key.

You can read more about this here.

. . .

As of v3 there are few other changes that you should know about
(which might feel unexpected).
Navigating back in navigator —

To navigate in a navigator if you use navigate  , then going back will


always take you to initialRoute of that navigator. You can prevent
that in drawer and tab by providing backBehavior: ‘none' but that
gives rise to different cases too.

If you have the following setup —

App
|- Stack1
|- Screen1
|- Screen2
|- Screen3
|- Stack2
|- Screen4
|- Screen5
|- Screen6

And you are currently on Screen3  . Now when you call


navigate('Screen6') you will go to Screen6  . From here if you go
back normally, you will first go to Screen4 then to Screen3  .

If you need navigating back from Screen6 to Screen3 you need to call
dispatch function with custom action  .

this.props.navigation.dispatch(
NavigationActions.navigate({
routeName: 'Stack2',
action: NavigationActions.navigate({
routeName: 'Screen6',
})
})
)

This works because when you pass action it prioritises child action
than the top level action. See details in this PR.

For this case you can also manually go back via


props.navigation.goBack(null) or props.navigation.pop()  .

You should also keep in mind similar case does not work for
DrawerNavigator .
I have made a Snack Expo where you can find various cases where
simply calling props.navigation.goBack() or pressing hardware back
button (without adding event handler) would not take you back as you
expect them to.

. . .

Conclusion
Learning React Navigation is easy. Initial stages are easier too. But as an
app grows more complex it becomes necessary to make a right choice in the
structure of the navigation of the app as you would not be able to make it
work with different type of navigator(like whether to register a component
inside a stack or a tab or a drawer ).

Before going into React Navigation you should keep in mind that, it is
still new and may contain bugs and side effects. It can happen that you
got stuck in one problem for long hours. So before going into any
navigation plugin do your research thoroughly.

. . .

That’s all for now. Hope you find this useful. If you think this can help
someone else too, pass it on.

Peace!

Das könnte Ihnen auch gefallen