diff --git a/versioned_docs/version-7.x/auth-flow.md b/versioned_docs/version-7.x/auth-flow.md
index 9cc509c29da..8241522d51e 100755
--- a/versioned_docs/version-7.x/auth-flow.md
+++ b/versioned_docs/version-7.x/auth-flow.md
@@ -22,17 +22,52 @@ We say "authentication screens" because usually there is more than one. You may
## What we need
-This is the 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 related to authentication, and when we press the hardware back button, we expect to not be able to go back to the authentication flow.
+We want the following behavior from our authentication flow:
-## How it will work
+- When the user is signed in, we want to show the main app screens and not the authentication-related screens.
+- When the user is signed out, we want to show the authentication screens and not the main app screens.
+- After the user goes through the authentication flow and signs in, we want to unmount all of the screens related to authentication, and when we press the hardware back button, we expect to not be able to go back to the authentication flow.
-We can define different screens based on some condition. For example, if the user is signed in, we can define `Home`, `Profile`, `Settings` etc. If the user is not signed in, we can define `SignIn` and `SignUp` screens.
+## How it will work
-For example:
+We can configure different screens to be available based on some condition. For example, if the user is signed in, we can define `Home`, `Profile`, `Settings` etc. If the user is not signed in, we can define `SignIn` and `SignUp` screens.
+To do this, we need a couple of things:
+
+1. Define two hooks: `useIsSignedIn` and `useIsSignedOut`, which return a boolean value indicating whether the user is signed in or not.
+2. Use the `useIsSignedIn` and `useIsSignedOut` along with the [`if`](static-configuration.md#if) property to define the screens that are available based on the condition.
+
+This tells React Navigation to show specific screens based on the signed in status. When the signed in status changes, React Navigation will automatically show the appropriate screen.
+
+## Define the hooks
+
+To implement the `useIsSignedIn` and `useIsSignedOut` hooks, we can start by creating a context to store the authentication state. Let's call it `SignInContext`:
+
+```js
+import * as React from 'react';
+
+const SignInContext = React.createContext();
+```
+
+Then we can implement the `useIsSignedIn` and `useIsSignedOut` hooks as follows:
+
+```js
+function useIsSignedIn() {
+ const isSignedIn = React.useContext(SignInContext);
+ return isSignedIn;
+}
+
+function useIsSignedOut() {
+ const isSignedIn = React.useContext(SignInContext);
+ return !isSignedIn;
+}
+```
+
+We'll discuss how to expose the context value later.
+
```js name="Customizing tabs appearance" snack version=7
import * as React from 'react';
import { View } from 'react-native';
@@ -113,6 +148,8 @@ function SignUpScreen() {
+For example:
+
```js name="Customizing tabs appearance" snack version=7
import * as React from 'react';
import { View } from 'react-native';
@@ -172,9 +209,6 @@ function SignUpScreen() {
}
```
-
-
-
When we define screens like this, when `isSignedIn` is `true`, React Navigation will only see the `Home`, `Profile` and `Settings` screens, and when it's `false`, React Navigation will see the `SignIn` and `SignUp` screens. This makes it impossible to navigate to the `Home`, `Profile` and `Settings` screens when the user is not signed in, and to `SignIn` and `SignUp` screens when the user is signed in.
This pattern has been in use by other routing libraries such as React Router for a long time, and is commonly known as "Protected routes". Here, our screens which need the user to be signed in are "protected" and cannot be navigated to by other means if the user is not signed in.
@@ -185,9 +219,8 @@ The example shows stack navigator, but you can use the same approach with any na
By conditionally defining different screens based on a variable, we can implement auth flow in a simple way that doesn't require additional logic to make sure that the correct screen is shown.
-## Don't manually navigate when conditionally rendering screens
-
-It's important to note that when using such a setup, you **don't manually navigate** to the `Home` screen by calling `navigation.navigate('Home')` or any other method. **React Navigation will automatically navigate to the correct screen** when `isSignedIn` changes - `Home` screen when `isSignedIn` becomes `true`, and to `SignIn` screen when `isSignedIn` becomes `false`. You'll get an error if you attempt to navigate manually.
+
+
## Define our screens
@@ -202,250 +235,111 @@ So our navigator will look like:
-```js name="Conditional rendering of screens" snack version=7
-import * as React from 'react';
-import {
- Text,
- TextInput,
- View,
- Button,
- ActivityIndicator,
- StyleSheet,
-} from 'react-native';
-import { createStaticNavigation } from '@react-navigation/native';
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
-
-const SignInContext = React.createContext();
-
-function useIsSignedIn() {
- const isSignedIn = React.useContext(SignInContext);
- return isSignedIn;
-}
-
-function useIsSignedOut() {
- const isSignedIn = React.useContext(SignInContext);
- return !isSignedIn;
-}
-
-const styles = StyleSheet.create({
- input: {
- height: 40,
- margin: 12,
- borderWidth: 1,
- padding: 10,
+```js
+const RootStack = createNativeStackNavigator({
+ screens: {
+ Home: {
+ if: useIsSignedIn,
+ screen: HomeScreen,
+ },
+ SignIn: {
+ if: useIsSignedOut,
+ screen: SignInScreen,
+ options: {
+ title: 'Sign in',
+ },
+ },
},
});
-function SplashScreen() {
- return (
-
- Getting token...
-
-
- );
-}
+const Navigation = createStaticNavigation(RootStack);
+```
-function HomeScreen() {
- return (
-
- Home Screen
-
- );
-}
+Notice how we have only defined the `Home` and `SignIn` screens here, and not the `SplashScreen`. The `SplashScreen` should be rendered before we render any navigators so that we don't render incorrect screens before we know whether the user is signed in or not.
-function SimpleSignInScreen({ route }) {
- const [email, setEmail] = React.useState('');
- const [password, setPassword] = React.useState('');
- const { setUserToken } = route.params;
+When we use this in our component, it'd look something like this:
- return (
-
- Email
-
- Password
-
-
- );
+```js
+if (isLoading) {
+ // We haven't finished checking for the token yet
+ return ;
}
-export default function App() {
- const [isLoading, setIsLoading] = React.useState(true);
- const [userToken, setUserToken] = React.useState(null);
-
- const getUserToken = async () => {
- // testing purposes
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- try {
- // custom logic
- await sleep(2000);
- const token = null;
- setUserToken(token);
- } finally {
- setIsLoading(false);
- }
- };
+const isSignedIn = userToken != null;
- React.useEffect(() => {
- getUserToken();
- }, []);
-
- // codeblock-focus-start
- if (isLoading) {
- // We haven't finished checking for the token yet
- return ;
- }
- const RootStack = createNativeStackNavigator({
- screens: {
- Home: {
- if: useIsSignedIn,
- screen: HomeScreen,
- },
- SignIn: {
- screen: SimpleSignInScreen,
- initialParams: {
- setUserToken,
- },
- options: {
- title: 'Sign in',
- },
- if: useIsSignedOut,
- },
- },
- });
-
- const Navigation = createStaticNavigation(RootStack);
-
- const isSignedIn = userToken != null;
-
- return (
-
-
-
- );
-}
-// codeblock-focus-end
+return (
+
+
+
+);
```
-
-
+In the above snippet, `isLoading` means that we're still checking if we have a token. This can usually be done by checking if we have a token in `SecureStore` and validating the token. After we get the token and if it's valid, we need to set the `userToken`. We also have another state called `isSignout` to have a different animation on sign out.
-```js name="Conditional rendering of screens" snack version=7
-import * as React from 'react';
-import {
- Text,
- TextInput,
- View,
- Button,
- ActivityIndicator,
- StyleSheet,
-} from 'react-native';
-import { NavigationContainer } from '@react-navigation/native';
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
+Next, we're exposing the sign in status via the `SignInContext` so that it's available to the `useIsSignedIn` and `useIsSignedOut` hooks.
-const Stack = createNativeStackNavigator();
+In the above example, we're have one screen for each case. But you could also define multiple screens. For example, you probably want to define password reset, signup, etc screens as well when the user isn't signed in. Similarly for the screens accessible after sign in, you probably have more than one screen. We can use [`groups`](static-configuration.md#groups) to define multiple screens:
-const styles = StyleSheet.create({
- input: {
- height: 40,
- margin: 12,
- borderWidth: 1,
- padding: 10,
+```js
+const RootStack = createNativeStackNavigator({
+ screens: {
+ // Common screens
+ },
+ groups: {
+ SignedIn: {
+ if: useIsSignedIn,
+ screens: {
+ Home: HomeScreen,
+ Profile: ProfileScreen,
+ },
+ },
+ SignedOut: {
+ if: useIsSignedOut,
+ screens: {
+ SignIn: SignInScreen,
+ SignUp: SignUpScreen,
+ ResetPassword: ResetPasswordScreen,
+ },
+ },
},
});
+```
-function SplashScreen() {
- return (
-
- Getting token...
-
-
- );
-}
-
-function HomeScreen() {
- return (
-
- Home Screen
-
- );
-}
-
-function SimpleSignInScreen({ navigation, route }) {
- const [email, setEmail] = React.useState('');
- const [password, setPassword] = React.useState('');
- const { setUserToken } = route.params;
-
- return (
-
- Email
-
- Password
-
-
- );
-}
+:::tip
-export default function App() {
- const [isLoading, setIsLoading] = React.useState(true);
- const [userToken, setUserToken] = React.useState(null);
-
- const getUserToken = async () => {
- // testing purposes
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- try {
- // custom logic
- await sleep(2000);
- const token = null;
- setUserToken(token);
- } finally {
- setIsLoading(false);
- }
- };
+If you have both your login-related screens and rest of the screens in Stack navigators, we recommend to use a single Stack navigator and place the conditional inside instead of using 2 different navigators. This makes it possible to have a proper transition animation during login/logout.
- React.useEffect(() => {
- getUserToken();
- }, []);
+:::
- // codeblock-focus-start
- if (isLoading) {
- // We haven't finished checking for the token yet
- return ;
- }
+
+
- return (
-
-
- {userToken == null ? (
- // No token found, user isn't signed in
-
- ) : (
- // User is signed in
-
- )}
-
-
- );
- // codeblock-focus-end
-}
+```js
+if (isLoading) {
+ // We haven't finished checking for the token yet
+ return ;
+}
+
+return (
+
+
+ {userToken == null ? (
+ // No token found, user isn't signed in
+
+ ) : (
+ // User is signed in
+
+ )}
+
+
+);
```
@@ -539,7 +433,7 @@ So we need to:
We'll use `React.useReducer` and `React.useContext` in this guide. But if you're using a state management library such as Redux or Mobx, you can use them for this functionality instead. In fact, in bigger apps, a global state management library is more suitable for storing authentication tokens. You can adapt the same approach to your state management library.
-First we'll need to create a context for auth where we can expose necessary methods:
+First we'll need to create a context for auth where we can expose the necessary methods:
```js
import * as React from 'react';
@@ -558,7 +452,11 @@ So our component will look like this:
```js name="Signing in and signing out with AuthContext" snack version=7
+// codeblock-focus-start
import * as React from 'react';
+import * as SecureStore from 'expo-secure-store';
+
+// codeblock-focus-end
import { Button, Text, TextInput, View } from 'react-native';
import { createStaticNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
@@ -659,7 +557,7 @@ export default function App() {
try {
// Restore token stored in `SecureStore` or any other encrypted storage
- // userToken = await SecureStore.getItemAsync('userToken');
+ userToken = await SecureStore.getItemAsync('userToken');
} catch (e) {
// Restoring token failed
}
@@ -702,25 +600,6 @@ export default function App() {
return ;
}
- const RootStack = createNativeStackNavigator({
- screens: {
- Home: {
- if: useIsSignedIn,
- screen: HomeScreen,
- },
- SignIn: {
- screen: SignInScreen,
- options: {
- title: 'Sign in',
- animationTypeForReplace: state.isSignout ? 'pop' : 'push',
- },
- if: useIsSignedOut,
- },
- },
- });
-
- const Navigation = createStaticNavigation(RootStack);
-
if (state.isLoading) {
return ;
}
@@ -736,6 +615,24 @@ export default function App() {
);
}
+const RootStack = createNativeStackNavigator({
+ screens: {
+ Home: {
+ if: useIsSignedIn,
+ screen: HomeScreen,
+ },
+ SignIn: {
+ screen: SignInScreen,
+ options: {
+ title: 'Sign in',
+ animationTypeForReplace: state.isSignout ? 'pop' : 'push',
+ },
+ if: useIsSignedOut,
+ },
+ },
+});
+
+const Navigation = createStaticNavigation(RootStack);
// codeblock-focus-end
```
@@ -743,7 +640,11 @@ export default function App() {
```js name="Signing in and signing out with AuthContext" snack version=7
+// codeblock-focus-start
import * as React from 'react';
+import * as SecureStore from 'expo-secure-store';
+
+// codeblock-focus-end
import { Button, Text, TextInput, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
@@ -834,7 +735,7 @@ export default function App() {
try {
// Restore token stored in `SecureStore` or any other encrypted storage
- // userToken = await SecureStore.getItemAsync('userToken');
+ userToken = await SecureStore.getItemAsync('userToken');
} catch (e) {
// Restoring token failed
}
@@ -945,39 +846,26 @@ Consider the following example:
```js
-const signedInStack = createNativeStackNavigator({
- screens: {
- Home: HomeScreen,
- Profile: ProfileScreen,
- Help: HelpScreen,
- },
-});
-
-const signedOutStack = createNativeStackNavigator({
- screens: {
- SignIn: SignInScreen,
- SignUp: SignUpScreen,
- Help: HelpScreen,
- },
-});
-
const RootStack = createNativeStackNavigator({
- screens: {
+ groups: {
LoggedIn: {
if: useIsSignedIn,
- screen: signedInStack,
- options: {
- headerShown: false,
+ screens: {
+ Home: HomeScreen,
+ Profile: ProfileScreen,
+ Help: HelpScreen,
},
},
LoggedOut: {
if: useIsSignedOut,
- screen: signedOutStack,
- options: {
- headerShown: false,
+ screens: {
+ SignIn: SignInScreen,
+ SignUp: SignUpScreen,
+ Help: HelpScreen,
},
},
},
+ screens: {},
});
```
@@ -1005,7 +893,7 @@ isSignedIn ? (
Here we have specific screens such as `SignIn`, `Home` etc. which are only shown depending on the sign in state. But we also have the `Help` screen which can be shown in both cases. This also means that if the signin state changes when the user is in the `Help` screen, they'll stay on the `Help` screen.
-This can be a problem, we probably want the user to be taken to the `SignIn` screen or `Home` screen instead of keeping them on the `Help` screen. To make this work, we can use the [`navigationKey` prop](screen.md#navigationkey). When the `navigationKey` changes, React Navigation will remove all the screen.
+This can be a problem, we probably want the user to be taken to the `SignIn` screen or `Home` screen instead of keeping them on the `Help` screen. To make this work, we can use [`navigationKey`](screen.md#navigationkey). When the `navigationKey` changes, React Navigation will remove all the screen.
So our updated code will look like following:
@@ -1013,36 +901,24 @@ So our updated code will look like following:
```js
-const signedInStack = createNativeStackNavigator({
- screens: {
- Home: HomeScreen,
- Profile: ProfileScreen,
- },
-});
-
-const signedOutStack = createNativeStackNavigator({
- screens: {
- SignIn: SignInScreen,
- SignUp: SignUpScreen,
- },
-});
-
const RootStack = createNativeStackNavigator({
- screens: {
+ groups: {
LoggedIn: {
if: useIsSignedIn,
- screen: signedInStack,
- options: {
- headerShown: false,
+ screens: {
+ Home: HomeScreen,
+ Profile: ProfileScreen,
},
},
LoggedOut: {
if: useIsSignedOut,
- screen: signedOutStack,
- options: {
- headerShown: false,
+ screens: {
+ SignIn: SignInScreen,
+ SignUp: SignUpScreen,
},
},
+ },
+ screens: {
Help: {
screen: HelpScreen,
navigationKey: isSignedIn ? 'user' : 'guest',
@@ -1084,49 +960,31 @@ If you have a bunch of shared screens, you can also use [`navigationKey` with a
```js
-const signedInStack = createNativeStackNavigator({
- screens: {
- Home: HomeScreen,
- Profile: ProfileScreen,
- },
-});
-
-const signedOutStack = createNativeStackNavigator({
- screens: {
- SignIn: SignInScreen,
- SignUp: SignUpScreen,
- },
-});
-
const RootStack = createNativeStackNavigator({
- screens: {
+ groups: {
LoggedIn: {
if: useIsSignedIn,
- screen: signedInStack,
- options: {
- headerShown: false,
+ screens: {
+ Home: HomeScreen,
+ Profile: ProfileScreen,
},
},
LoggedOut: {
if: useIsSignedOut,
- screen: signedOutStack,
- options: {
- headerShown: false,
+ screens: {
+ SignIn: SignInScreen,
+ SignUp: SignUpScreen,
},
},
- },
- groups: {
Common: {
navigationKey: isSignedIn ? 'user' : 'guest',
- screenOptions: {
- headerShown: false,
- },
screens: {
Help: HelpScreen,
About: AboutScreen,
},
},
},
+ screens: {},
});
```
@@ -1155,3 +1013,7 @@ const RootStack = createNativeStackNavigator({
+
+## Don't manually navigate when conditionally rendering screens
+
+It's important to note that when using such a setup, you **don't manually navigate** to the `Home` screen by calling `navigation.navigate('Home')` or any other method. **React Navigation will automatically navigate to the correct screen** when `isSignedIn` changes - `Home` screen when `isSignedIn` becomes `true`, and to `SignIn` screen when `isSignedIn` becomes `false`. You'll get an error if you attempt to navigate manually.
diff --git a/versioned_docs/version-7.x/static-combine-with-dynamic.md b/versioned_docs/version-7.x/combine-static-with-dynamic.md
similarity index 97%
rename from versioned_docs/version-7.x/static-combine-with-dynamic.md
rename to versioned_docs/version-7.x/combine-static-with-dynamic.md
index d8a65aed213..38a2d210c2a 100644
--- a/versioned_docs/version-7.x/static-combine-with-dynamic.md
+++ b/versioned_docs/version-7.x/combine-static-with-dynamic.md
@@ -1,7 +1,7 @@
---
-id: static-combine-with-dynamic
+id: combine-static-with-dynamic
title: Combining static and dynamic APIs
-sidebar_label: Combining with dynamic API
+sidebar_label: Combining static and dynamic APIs
---
While the static API has many advantages, it doesn't fit use cases where the navigation configuration needs to be dynamic. So React Navigation supports interop between the static and dynamic APIs.
diff --git a/versioned_docs/version-7.x/nesting-navigators.md b/versioned_docs/version-7.x/nesting-navigators.md
index b74e933c305..72aa781b274 100755
--- a/versioned_docs/version-7.x/nesting-navigators.md
+++ b/versioned_docs/version-7.x/nesting-navigators.md
@@ -1039,7 +1039,7 @@ We recommend to reduce nesting navigators to minimal. Try to achieve the behavio
- Nesting same type of navigators (e.g. tabs inside tabs, drawer inside drawer etc.) might lead to a confusing UX
- With excessive nesting, code becomes difficult to follow when navigating to nested screens, configuring deep link etc.
-Think of nesting navigators as a way to achieve the UI you want rather than a way to organize your code. If you want to create separate group of screens for organization, instead of using separate navigators, you can use the [`Group`](group.md) component for dynamic configuration or [`groups` property](static-api-reference.md#groups) for static configuration.
+Think of nesting navigators as a way to achieve the UI you want rather than a way to organize your code. If you want to create separate group of screens for organization, instead of using separate navigators, you can use the [`Group`](group.md) component for dynamic configuration or [`groups` property](static-configuration.md#groups) for static configuration.
diff --git a/versioned_docs/version-7.x/static-authentication.md b/versioned_docs/version-7.x/static-authentication.md
deleted file mode 100644
index acfbec55ad4..00000000000
--- a/versioned_docs/version-7.x/static-authentication.md
+++ /dev/null
@@ -1,306 +0,0 @@
----
-id: static-authentication
-title: Authentication flow with static API
-sidebar_label: Authentication flow
----
-
-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:
-
-- The user opens the app.
-- The app loads some authentication state from encrypted persistent storage (for example, [`SecureStore`](https://docs.expo.io/versions/latest/sdk/securestore/)).
-- 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.
-- When the user signs out, we clear the authentication state and send them back to authentication screens.
-
-:::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.
-
-:::
-
-## What we need
-
-This is the 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 related to authentication, and when we press the hardware back button we expect to not be able to go back to the authentication flow.
-
-## How it will work
-
-We can configure different screens to be available based on some condition. For example, if the user is signed in, we can define `Home`, `Profile`, `Settings` etc. If the user is not signed in, we can define `SignIn` and `SignUp` screens. To do this, we need a couple of things:
-
-1. Define two hooks: `useIsSignedIn` and `useIsSignedOut`, which return a boolean value indicating whether the user is signed in or not.
-2. Use the `useIsSignedIn` and `useIsSignedOut` along with the [`if`](static-api-reference.md#if) property to define the screens that are available based on the condition.
-
-This tells React Navigation to show specific screens based on the signed in status. When the signed in status changes, React Navigation will automatically show the appropriate screen.
-
-## Don't manually navigate when using `if` for conditional screens
-
-It's important to note that when using such a setup, you **don't manually navigate** to the `Home` screen by calling `navigation.navigate('Home')` or any other method. **React Navigation will automatically navigate to the correct screen** when `isSignedIn` changes - `Home` screen when `isSignedIn` becomes `true`, and to `SignIn` screen when `isSignedIn` becomes `false`. You'll get an error if you attempt to navigate manually.
-
-## Define the hooks
-
-To implement the `useIsSignedIn` and `useIsSignedOut` hooks, we can start by creating a context to store the authentication state. Let's call it `SignInContext`:
-
-```js
-import * as React from 'react';
-
-const SignInContext = React.createContext();
-```
-
-Then we can implement the `useIsSignedIn` and `useIsSignedOut` hooks as follows:
-
-```js
-function useIsSignedIn() {
- const isSignedIn = React.useContext(SignInContext);
- return isSignedIn;
-}
-
-function useIsSignedOut() {
- const isSignedIn = React.useContext(SignInContext);
- return !isSignedIn;
-}
-```
-
-We'll discuss how to expose the context value later.
-
-## Define our screens
-
-For our case, let's say we have 3 screens:
-
-- `SplashScreen` - This will show a splash or loading screen when we're restoring the token.
-- `SignIn` - This is the screen we show if the user isn't signed in already (we couldn't find a token).
-- `Home` - This is the screen we show if the user is already signed in.
-
-We'd have our navigation tree defined with these screens as follows:
-
-```js
-const RootStack = createNativeStackNavigator({
- screens: {
- Home: {
- if: useIsSignedIn,
- screen: HomeScreen,
- },
- SignIn: {
- if: useIsSignedOut,
- screen: SignInScreen,
- options: {
- title: 'Sign in',
- },
- },
- },
-});
-
-const Navigation = createStaticNavigation(RootStack);
-```
-
-Notice how we have only defined the `Home` and `SignIn` screens here, and not the `SplashScreen`. The `SplashScreen` should be rendered before we render any navigators so that we don't render incorrect screens before we know whether the user is signed in or not.
-
-When we use this in our component, it'd look something like this:
-
-```js
-if (state.isLoading) {
- // We haven't finished checking for the token yet
- return ;
-}
-
-const isSignedIn = state.userToken != null;
-
-return (
-
-
-
-);
-```
-
-In the above snippet, `isLoading` means that we're still checking if we have a token. This can usually be done by checking if we have a token in `SecureStore` and validating the token. After we get the token and if it's valid, we need to set the `userToken`. We also have another state called `isSignout` to have a different animation on sign out.
-
-Next, we're exposing the sign in status via the `SignInContext` so that it's available to the `useIsSignedIn` and `useIsSignedOut` hooks.
-
-In the above example, we're have one screen for each case. But you could also define multiple screens. For example, you probably want to define password reset, signup, etc screens as well when the user isn't signed in. Similarly for the screens accessible after sign in, you probably have more than one screen. We can use [`groups`](static-api-reference.md#groups) to define multiple screens:
-
-```js
-const RootStack = createNativeStackNavigator({
- screens: {
- // Common screens
- },
- groups: {
- SignedIn: {
- if: useIsSignedIn,
- screens: {
- Home: HomeScreen,
- Profile: ProfileScreen,
- },
- },
- SignedOut: {
- if: useIsSignedOut,
- screens: {
- SignIn: SignInScreen,
- SignUp: SignUpScreen,
- ResetPassword: ResetPasswordScreen,
- },
- },
- },
-});
-```
-
-:::tip
-
-If you have both your login-related screens and rest of the screens in Stack navigators, we recommend to use a single Stack navigator and place the conditional inside instead of using 2 different navigators. This makes it possible to have a proper transition animation during login/logout.
-
-:::
-
-## Implement the logic for restoring the token
-
-:::note
-
-The following is just an example of how you might implement the logic for authentication in your app. You don't need to follow it as is.
-
-:::
-
-From the previous snippet, we can see that we need 2 state variables:
-
-- `isLoading` - We set this to `true` when we're trying to check if we already have a token saved in `SecureStore`
-- `userToken` - The token for the user. If it's non-null, we assume the user is logged in, otherwise not.
-
-So we need to:
-
-- Add some logic for restoring token, sign in and sign out
-- Expose methods for sign in and sign out to other components
-
-We'll use `React.useReducer` and `React.useContext` in this guide. But if you're using a state management library such as Redux or Mobx, you can use them for this functionality instead. In fact, in bigger apps, a global state management library is more suitable for storing authentication tokens. You can adapt the same approach to your state management library.
-
-First we'll need to create a context for auth where we can expose necessary methods:
-
-```js
-import * as React from 'react';
-
-const AuthContext = React.createContext();
-```
-
-In our component, we will:
-
-- Store the token and loading state in `useReducer`
-- Persist it to `SecureStore` and read it from there on app launch
-- Expose the methods for sign in and sign out to child components using `AuthContext`
-
-So we'll have something like this:
-
-```js
-import * as React from 'react';
-import * as SecureStore from 'expo-secure-store';
-
-export default function App({ navigation }) {
- const [state, dispatch] = React.useReducer(
- (prevState, action) => {
- switch (action.type) {
- case 'RESTORE_TOKEN':
- return {
- ...prevState,
- userToken: action.token,
- isLoading: false,
- };
- case 'SIGN_IN':
- return {
- ...prevState,
- userToken: action.token,
- };
- case 'SIGN_OUT':
- return {
- ...prevState,
- userToken: null,
- };
- }
- },
- {
- isLoading: true,
- userToken: null,
- }
- );
-
- React.useEffect(() => {
- // Fetch the token from storage then navigate to our appropriate place
- const bootstrapAsync = async () => {
- let userToken;
-
- try {
- userToken = await SecureStore.getItemAsync('userToken');
- } catch (e) {
- // Restoring token failed
- }
-
- // After restoring token, we may need to validate it in production apps
- // ...
-
- // This will switch to the App screen or Auth screen and this loading
- // screen will be unmounted and thrown away.
- dispatch({ type: 'RESTORE_TOKEN', token: userToken });
- };
-
- bootstrapAsync();
- }, []);
-
- const authContext = React.useMemo(
- () => ({
- signIn: async (data) => {
- // In a production app, we need to send some data (usually username, password) to server and get a token
- // We will also need to handle errors if sign in failed
- // After getting token, we need to persist the token using `SecureStore`
- // In the example, we'll use a dummy token
-
- dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
- },
- signOut: () => dispatch({ type: 'SIGN_OUT' }),
- signUp: async (data) => {
- // In a production app, we need to send user data to server and get a token
- // We will also need to handle errors if sign up failed
- // After getting token, we need to persist the token using `SecureStore`
- // In the example, we'll use a dummy token
-
- dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
- },
- }),
- []
- );
-
- if (state.isLoading) {
- return ;
- }
-
- return (
-
-
-
-
-
- );
-}
-```
-
-## Fill in other components
-
-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.
-
-```js
-function SignInScreen() {
- const [username, setUsername] = React.useState('');
- const [password, setPassword] = React.useState('');
-
- const { signIn } = React.useContext(AuthContext);
-
- return (
-
-
-
-
- );
-}
-```
-
-You can similarly fill in the other screens according to your requirements.
diff --git a/versioned_docs/version-7.x/static-api-reference.md b/versioned_docs/version-7.x/static-configuration.md
similarity index 96%
rename from versioned_docs/version-7.x/static-api-reference.md
rename to versioned_docs/version-7.x/static-configuration.md
index e297650eb8b..df758bc47e9 100644
--- a/versioned_docs/version-7.x/static-api-reference.md
+++ b/versioned_docs/version-7.x/static-configuration.md
@@ -1,7 +1,7 @@
---
-id: static-api-reference
-title: Static API Reference
-sidebar_label: API Reference
+id: static-configuration
+title: Static configuration
+sidebar_label: Static configuration
---
The bulk of the static configuration is done using the `createXNavigator` functions, e.g. [`createNativeStackNavigator`](native-stack-navigator.md), [`createBottomTabNavigator`](bottom-tab-navigator.md), [`createDrawerNavigator`](drawer-navigator.md) etc. We'll refer to these functions as `createXNavigator` in the rest of this guide.
@@ -167,7 +167,7 @@ const RootStack = createNativeStackNavigator({
The `linking` object supports the same configuration options described in [Configuring links](configuring-links.md) such as `parse`, `stringify` and `exact`.
-To make deep links work on native apps, you also need to [configure your app](deep-linking.md) and pass `prefixes` to the navigation component returned by [`createStaticNavigation`](static-api-reference.md#createstaticnavigation):
+To make deep links work on native apps, you also need to [configure your app](deep-linking.md) and pass `prefixes` to the navigation component returned by [`createStaticNavigation`](static-configuration.md#createstaticnavigation):
```js
const Navigation = createStaticNavigation(RootStack);
@@ -206,7 +206,7 @@ const RootStack = createNativeStackNavigator({
The above example will only render the `HomeScreen` if the user is logged in.
-For more details, see [Authentication flow with static API](static-authentication.md).
+For more details, see [Authentication flow](auth-flow.md?config=static).
#### `options`
@@ -322,7 +322,7 @@ const RootStackNavigator = createComponentForStaticNavigation(RootStack, 'RootNa
The returned component doesn't take any props. All of the configuration is inferred from the static config. It's essentially the same as defining a component using the dynamic API.
-This looks similar to `createStaticNavigation` however they are very different. When using static configuration, you'd never use this function directly. The only time you'd use this is if you're migrating away from static configuration and want to reuse existing code you wrote instead of rewriting it to the dynamic API. See [Combining static and dynamic APIs](static-combine-with-dynamic.md) for more details.
+This looks similar to `createStaticNavigation` however they are very different. When using static configuration, you'd never use this function directly. The only time you'd use this is if you're migrating away from static configuration and want to reuse existing code you wrote instead of rewriting it to the dynamic API. See [Combining static and dynamic APIs](combine-static-with-dynamic.md) for more details.
## `createPathConfigForStaticNavigation`
@@ -338,4 +338,4 @@ const config = {
};
```
-Similar to `createComponentForStaticNavigation`, this is intended to be used when migrating away from static configuration. See [Combining static and dynamic APIs](static-combine-with-dynamic.md) for more details.
+Similar to `createComponentForStaticNavigation`, this is intended to be used when migrating away from static configuration. See [Combining static and dynamic APIs](combine-static-with-dynamic.md) for more details.
diff --git a/versioned_sidebars/version-7.x-sidebars.json b/versioned_sidebars/version-7.x-sidebars.json
index 6bc7ddb531e..eaad2509f3f 100644
--- a/versioned_sidebars/version-7.x-sidebars.json
+++ b/versioned_sidebars/version-7.x-sidebars.json
@@ -33,6 +33,7 @@
"screen-tracking",
"themes",
"state-persistence",
+ "combine-static-with-dynamic",
"testing",
"typescript",
"redux-integration",
@@ -40,11 +41,6 @@
"troubleshooting",
"upgrading-from-6.x"
],
- "Static configuration": [
- "static-api-reference",
- "static-authentication",
- "static-combine-with-dynamic"
- ],
"Navigators": [
"stack-navigator",
"native-stack-navigator",
@@ -59,6 +55,7 @@
"drawer-layout"
],
"API reference": [
+ "static-configuration",
"navigation-container",
"server-container",
"group",