You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: versioned_docs/version-7.x/auth-flow.md
+57-128
Original file line number
Diff line number
Diff line change
@@ -30,12 +30,12 @@ We want the following behavior from our authentication flow:
30
30
31
31
## How it will work
32
32
33
-
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.
33
+
We can configure different screens to be available based on some condition. For example, if the user is signed in, we want `Home` to be available. If the user is not signed in, we want `SignIn`to be available.
Here, for each screen, we have defined a condition using the `if` property which takes a hook. The hook returns a boolean value indicating whether the user is signed in or not. If the hook returns `true`, the screen will be available, otherwise it won't.
105
83
106
-
functionSignInScreen() {
107
-
return<View />;
84
+
When `useIsSignedIn` returns `true`, React Navigation will only use the `Home` screen, and when it returns `false`, React Navigation will use the `SignIn` screen. This makes it impossible to navigate to the `Home` when the user is not signed in, and to `SignIn` when the user is signed in.
85
+
86
+
The magic happens when the value returned by `useIsSignedin` changes. Let's say, initially `useIsSignedIn` returns `false`. This means that `SignIn` screens is shown. After the user signs in, the return value of `useIsSignedIn` will change to `true`. React Navigation will see that the `SignIn` screen is no longer defined and so it will remove it. Then it'll show the `Home` screen automatically because that's the first screen defined when `useIsSignedIn` returns `true`.
87
+
88
+
## Define the hooks
89
+
90
+
To implement the `useIsSignedIn` and `useIsSignedOut` hooks, we can start by creating a context to store the authentication state. Let's call it `SignInContext`:
91
+
92
+
```js
93
+
import*asReactfrom'react';
94
+
95
+
constSignInContext=React.createContext();
96
+
```
97
+
98
+
Then we can implement the `useIsSignedIn` and `useIsSignedOut` hooks as follows:
99
+
100
+
```js
101
+
functionuseIsSignedIn() {
102
+
constisSignedIn=React.useContext(SignInContext);
103
+
return isSignedIn;
108
104
}
109
105
110
-
functionSignUpScreen() {
111
-
return<View />;
106
+
functionuseIsSignedOut() {
107
+
constisSignedIn=React.useContext(SignInContext);
108
+
return!isSignedIn;
112
109
}
113
110
```
114
111
112
+
We'll discuss how to provide the context value later.
Here, we have conditionally defined the screens based on the value of `isSignedIn`.
183
154
184
-
When `useIsSignedIn` returns`true`, React Navigation will only see the `Home`, `Profile` and `Settings` screens, and when it returns `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.
155
+
When `isSignedIn` is`true`, React Navigation will only see the `Home` screen, and when it returns `false`, React Navigation will see the `SignIn`screen. This makes it impossible to navigate to the `Home`when the user is not signed in, and to `SignIn` when the user is signed in.
185
156
186
157
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.
187
158
188
-
The magic happens when the value returned by `useIsSignedin` changes. Let's say, initially `useIsSignedIn` returns `false`. This means, either `SignIn` or `SignUp` screens are shown. After the user signs in, the return value of `useIsSignedIn` will change to `true`. React Navigation will see that the `SignIn` and `SignUp` screens are no longer defined and so it will remove them. Then it'll show the `Home` screen automatically because that's the first screen defined when `useIsSignedIn` returns `true`.
189
-
190
-
The example shows stack navigator, but you can use the same approach with any navigator.
191
-
192
-
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.
193
-
194
-
To do this, we need a couple of things:
195
-
196
-
<TabsgroupId="config"queryString="config">
197
-
<TabItemvalue="static"label="Static"default>
198
-
199
-
1. Define two hooks: `useIsSignedIn` and `useIsSignedOut`, which return a boolean value indicating whether the user is signed in or not.
200
-
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.
201
-
202
-
</TabItem>
203
-
204
-
<TabItemvalue="dynamic"label="Dynamic">
205
-
206
-
1. Define two hooks: `useIsSignedIn` and `useIsSignedOut`, which return a boolean value indicating whether the user is signed in or not.
207
-
2. Use the `useIsSignedIn` and `useIsSignedOut` along with conditional rendering to define the screens that are available based on the condition.
159
+
The magic happens when the value of `isSignedin` changes. Let's say, initially `isSignedIn` returns `false`. This means that `SignIn` screens is shown. After the user signs in, the value of `isSignedIn` will change to `true`. React Navigation will see that the `SignIn` screen is no longer defined and so it will remove it. Then it'll show the `Home` screen automatically because that's the first screen defined when `isSignedIn` is `true`.
208
160
209
161
</TabItem>
210
162
</Tabs>
211
-
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.
212
163
213
-
## Define the hooks
164
+
## Add more screens
214
165
215
-
To implement the `useIsSignedIn` and `useIsSignedOut` hooks, we can start by creating a context to store the authentication state. Let's call it `SignInContext`:
216
-
217
-
```js
218
-
import*asReactfrom'react';
219
-
220
-
constSignInContext=React.createContext();
221
-
```
222
-
223
-
Then we can implement the `useIsSignedIn` and `useIsSignedOut` hooks as follows:
224
-
225
-
```js
226
-
functionuseIsSignedIn() {
227
-
constisSignedIn=React.useContext(SignInContext);
228
-
return isSignedIn;
229
-
}
230
-
231
-
functionuseIsSignedOut() {
232
-
constisSignedIn=React.useContext(SignInContext);
233
-
return!isSignedIn;
234
-
}
235
-
```
236
-
237
-
We'll discuss how to expose the context value later.
238
-
239
-
## Define our screens
240
-
241
-
In our navigator, we can conditionally define appropriate screens. For our case, let's say we have 3 screens:
166
+
For our case, let's say we have 3 screens:
242
167
243
168
-`SplashScreen` - This will show a splash or loading screen when we're restoring the token.
244
169
-`SignIn` - This is the screen we show if the user isn't signed in already (we couldn't find a token).
@@ -357,7 +282,7 @@ The main thing to notice is that we're conditionally defining screens based on t
357
282
-`SignIn` screen is only defined if `userToken` is `null` (user is not signed in)
358
283
-`Home` screen is only defined if `userToken` is non-null (user is signed in)
359
284
360
-
Here, we're conditionally defining 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 signing in, you probably have more than one screen. We can use `React.Fragment` to define multiple screens:
285
+
Here, we're conditionally defining 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 signing in, you probably have more than one screen. We can use [`React.Fragment`](https://react.dev/reference/react/Fragment) or [`Group`](group.md) to define multiple screens:
361
286
362
287
```js
363
288
isSignedIn ? (
@@ -374,15 +299,15 @@ isSignedIn ? (
374
299
);
375
300
```
376
301
377
-
</TabItem>
378
-
</Tabs>
379
-
380
302
:::tip
381
303
382
-
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.
304
+
If you have both your login-related screens and rest of the screens in two different Stack navigators and render them conditionally, 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.
383
305
384
306
:::
385
307
308
+
</TabItem>
309
+
</Tabs>
310
+
386
311
## Implement the logic for restoring the token
387
312
388
313
:::note
@@ -393,8 +318,8 @@ The following is just an example of how you might implement the logic for authen
393
318
394
319
From the previous snippet, we can see that we need 3 state variables:
395
320
396
-
-`isLoading` - We set this to `true` when we're trying to check if we already have a token saved in `SecureStore`
397
-
-`isSignout` - We set this to `true` when user is signing out, otherwise set it to `false`
321
+
-`isLoading` - We set this to `true` when we're trying to check if we already have a token saved in `SecureStore`.
322
+
-`isSignout` - We set this to `true` when user is signing out, otherwise set it to `false`. This can be used to customize the animation when signing out.
398
323
-`userToken` - The token for the user. If it's non-null, we assume the user is logged in, otherwise not.
@@ -946,6 +871,10 @@ If you have a bunch of shared screens, you can also use [`navigationKey` with a
946
871
</TabItem>
947
872
</Tabs>
948
873
874
+
The examples above show stack navigator, but you can use the same approach with any navigator.
875
+
876
+
By specifying a condition for our screens, we can implement auth flow in a simple way that doesn't require additional logic to make sure that the correct screen is shown.
877
+
949
878
## Don't manually navigate when conditionally rendering screens
950
879
951
880
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.
0 commit comments