From d10eea6a2797a5708eca80b87452b320335a231e Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 28 Feb 2024 16:08:59 +0100 Subject: [PATCH] Merge static configuration section with rest --- versioned_docs/version-7.x/auth-flow.md | 514 +++++++----------- ...amic.md => combine-static-with-dynamic.md} | 4 +- .../version-7.x/nesting-navigators.md | 2 +- .../version-7.x/static-authentication.md | 306 ----------- ...i-reference.md => static-configuration.md} | 14 +- versioned_sidebars/version-7.x-sidebars.json | 7 +- 6 files changed, 200 insertions(+), 647 deletions(-) rename versioned_docs/version-7.x/{static-combine-with-dynamic.md => combine-static-with-dynamic.md} (97%) delete mode 100644 versioned_docs/version-7.x/static-authentication.md rename versioned_docs/version-7.x/{static-api-reference.md => static-configuration.md} (96%) 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 - -