Skip to content

Commit de40e8a

Browse files
committed
Add SwitchNavigator reference and Authentication Flows guide
1 parent 98aa2d5 commit de40e8a

File tree

4 files changed

+203
-6
lines changed

4 files changed

+203
-6
lines changed

docs/auth-flow.md

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,135 @@
22
id: auth-flow
33
title: Authentication flows
44
sidebar_label: Authentication flows
5-
---
5+
---
6+
7+
Most apps require that a user authenticate in some way to have access to data associated with a user or other private content. Typically the flow will look like this:
8+
9+
* The user opens the app.
10+
* The app loads some authentication state from persistent storage (for example, `AsyncStorage`).
11+
* When the state has loaded, the user is presented with either authentication screens or the main app, depending on whether valid authentication state was loaded.
12+
* When the user signs out, we clear the authentication state and send them back to authentication screens.
13+
14+
> Note: we say "authentication screens" because usually there is more than one. You may have a main screen with a username and password field, another for "forgot password", and another set for sign up.
15+
16+
## Set up our navigators
17+
18+
```js
19+
import { StackNavigator, SwitchNavigator } from 'react-navigation';
20+
21+
// Implementation of HomeScreen, OtherScreen, SignInScreen, LoadingScreen
22+
// goes here.
23+
24+
const AppStack = StackNavigator({ Home: HomeScreen, Other: OtherScreen });
25+
const AuthStack = StackNavigator({ SignIn: SignInScreen });
26+
27+
export default SwitchNavigator(
28+
{
29+
AuthLoading: AuthLoadingScreen,
30+
App: AppStack,
31+
Auth: AuthStack,
32+
},
33+
{
34+
initialRouteName: 'AuthLoading',
35+
}
36+
);
37+
```
38+
<a href="https://snack.expo.io/@react-navigation/auth-flow" target="blank" class="run-code-button">&rarr; Run this code</a>
39+
40+
You may not be familiar with `SwitchNavigator` yet. The purpose of `SwitchNavigator` is to only ever show one screen at a time. By default, it does not handle back actions and it resets routes to their default state when you switch away. This is the exact behavior that we want from the authentication flow: when users sign in, we want to throw away the state of the authentication flow and unmount all of the screens, and when we press the hardware back button we expect to not be able to go back to the authentication flow. We switch between routes in the `SwitchNavigator` by using the `navigate` action. You can read more about the `SwitchNavigator` in the [API reference](/docs/switch-navigator).
41+
42+
We set the `initialRouteName` to `'AuthLoading'` because we will fetch our authentication state from persistent storage inside of that screen component.
43+
44+
## Implement our authentication loading screen
45+
46+
```js
47+
import React from 'react';
48+
import {
49+
ActivityIndicator,
50+
AsyncStorage,
51+
StatusBar,
52+
StyleSheet,
53+
View,
54+
} from 'react-native';
55+
56+
class AuthLoadingScreen extends React.Component {
57+
constructor() {
58+
super();
59+
this._bootstrapAsync();
60+
}
61+
62+
// Fetch the token from storage then navigate to our appropriate place
63+
_bootstrapAsync = async () => {
64+
const userToken = await AsyncStorage.getItem('userToken');
65+
66+
// This will switch to the App screen or Auth screen and this loading
67+
// screen will be unmounted and thrown away.
68+
this.props.navigation.navigate(userToken ? 'App' : 'Auth');
69+
};
70+
71+
// Render any loading content that you like here
72+
render() {
73+
return (
74+
<View style={styles.container}>
75+
<ActivityIndicator />
76+
<StatusBar barStyle="default" />
77+
</View>
78+
);
79+
}
80+
}
81+
```
82+
<a href="https://snack.expo.io/@react-navigation/auth-flow" target="blank" class="run-code-button">&rarr; Run this code</a>
83+
84+
## Fill in other components
85+
86+
Our `App` and `Auth` routes are both `StackNavigators`, but you could do whatever you like here. As mentioned above, you probably want your authentication route to be a stack for password reset, signup, etc. Similarly for your app, you probbaly have more than one screen. We won't talk about how to implement the text inputs and buttons for the authentication screen, that is outside of the scope of navigation. We'll just fill in some placeholder content.
87+
88+
```js
89+
class SignInScreen extends React.Component {
90+
static navigationOptions = {
91+
title: 'Please sign in',
92+
};
93+
94+
render() {
95+
return (
96+
<View style={styles.container}>
97+
<Button title="Sign in!" onPress={this._signInAsync} />
98+
</View>
99+
);
100+
}
101+
102+
_signInAsync = async () => {
103+
await AsyncStorage.setItem('userToken', 'abc');
104+
this.props.navigation.navigate('App');
105+
};
106+
}
107+
108+
class HomeScreen extends React.Component {
109+
static navigationOptions = {
110+
title: 'Welcome to the app!',
111+
};
112+
113+
render() {
114+
return (
115+
<View style={styles.container}>
116+
<Button title="Show me more of the app" onPress={this._showMoreApp} />
117+
<Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
118+
</View>
119+
);
120+
}
121+
122+
_showMoreApp = () => {
123+
this.props.navigation.navigate('Other');
124+
};
125+
126+
_signOutAsync = async () => {
127+
await AsyncStorage.clear();
128+
this.props.navigation.navigate('Auth');
129+
};
130+
}
131+
132+
// More code like OtherScreen omitted for brevity
133+
```
134+
<a href="https://snack.expo.io/@react-navigation/auth-flow" target="blank" class="run-code-button">&rarr; Run this code</a>
135+
136+
That's about all there is to it. At the moment, `SwitchNavigator` doesn't support animating between screens. Let us know if this is important to you [on Canny](https://react-navigation.canny.io/feature-requests).

docs/switch-navigator.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
id: switch-navigator
3+
title: SwitchNavigator reference
4+
sidebar_label: SwitchNavigator
5+
---
6+
7+
```js
8+
SwitchNavigator(RouteConfigs, SwitchNavigatorConfig)
9+
```
10+
11+
## RouteConfigs
12+
13+
The route configs object is a mapping from route name to a route config, which tells the navigator what to present for that route, see [example](stack-navigator.md#routeconfigs) from `StackNavigator`.
14+
15+
## SwitchNavigatorConfig
16+
17+
Several options get passed to the underlying router to modify navigation logic:
18+
19+
- `initialRouteName` - The routeName for the initial tab route when first loading.
20+
- `resetOnBlur` - Reset the state of any nested navigators when switching away from a screen. Defaults to `true`.
21+
- `paths` - Provide a mapping of routeName to path config, which overrides the paths set in the routeConfigs.
22+
- `backBehavior` - Should the back button cause a tab switch to the initial route? If yes, set to `initialRoute`, otherwise `none`. Defaults to `none` behavior.
23+
24+
## Example
25+
26+
See an example of this [on Snack](https://snack.expo.io/@react-navigation/auth-flow).

website/i18n/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
"StackNavigator": "StackNavigator",
9292
"status-bar": "Different status bar configuration based on route",
9393
"Different status bar configuration based on route": "Different status bar configuration based on route",
94+
"switch-navigator": "SwitchNavigator reference",
95+
"SwitchNavigator": "SwitchNavigator",
9496
"tab-based-navigation": "Tab navigation",
9597
"Tab navigation": "Tab navigation",
9698
"tab-navigator": "TabNavigator reference",
@@ -102,6 +104,7 @@
102104
"Docs": "Docs",
103105
"API": "API",
104106
"Help": "Help",
107+
"Blog": "Blog",
105108
"Fundamentals": "Fundamentals",
106109
"How do I do ...?": "How do I do ...?",
107110
"Build your own Navigator": "Build your own Navigator",

website/sidebars.json

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,48 @@
11
{
22
"docs": {
3-
"Fundamentals": ["getting-started", "hello-react-navigation", "navigating", "params", "headers", "header-buttons", "modal", "next-steps", "glossary-of-terms"],
4-
"How do I do ...?": ["tab-based-navigation", "drawer-based-navigation", "handling-iphonex", "status-bar", "custom-android-back-button-handling", "connecting-navigation-prop", "deep-linking", "screen-tracking", "redux-integration"],
5-
"Build your own Navigator": ["custom-navigator-overview", "routers", "custom-navigators", "custom-routers", "navigation-views", "transitioner"],
3+
"Fundamentals": [
4+
"getting-started",
5+
"hello-react-navigation",
6+
"navigating",
7+
"params",
8+
"headers",
9+
"header-buttons",
10+
"modal",
11+
"next-steps",
12+
"glossary-of-terms"
13+
],
14+
"How do I do ...?": [
15+
"tab-based-navigation",
16+
"drawer-based-navigation",
17+
"auth-flow",
18+
"handling-iphonex",
19+
"status-bar",
20+
"custom-android-back-button-handling",
21+
"connecting-navigation-prop",
22+
"deep-linking",
23+
"screen-tracking",
24+
"redux-integration"
25+
],
26+
"Build your own Navigator": [
27+
"custom-navigator-overview",
28+
"routers",
29+
"custom-navigators",
30+
"custom-routers",
31+
"navigation-views",
32+
"transitioner"
33+
],
634
"Meta": ["pitch", "alternatives", "contributing"]
735
},
836
"api": {
9-
"API Reference": ["api-reference", "navigation-prop", "navigation-actions", "stack-navigator", "tab-navigator", "drawer-navigator", "with-navigation"]
37+
"API Reference": [
38+
"api-reference",
39+
"navigation-prop",
40+
"navigation-actions",
41+
"stack-navigator",
42+
"switch-navigator",
43+
"tab-navigator",
44+
"drawer-navigator",
45+
"with-navigation"
46+
]
1047
}
11-
}
48+
}

0 commit comments

Comments
 (0)