在 React Native 中处理导航路由的挂载和卸载

已发表: 2022-03-10
快速总结↬通常您需要两组不同的导航堆栈来进行用户身份验证之前和之后。 通常,要查看更多内容,您必须以某种方式进行身份验证。 让我们看看如何在 React Native 中根据满足条件来挂载和卸载导航堆栈。

在本文中,我们将介绍 React Native中导航路由的挂载和卸载。 您的应用程序的预期行为是,一旦满足身份验证条件,一组新的导航路线仅对登录用户可用,而在身份验证之前显示的其他屏幕将被删除并且无法返回,除非用户退出应用程序。

为了您的应用程序的安全性,受保护的路由为您提供了一种仅向特定用户显示应用程序上的某些信息/内容的方法,同时限制未经授权的人员的访问。

我们将与 Expo 合作开展这个项目,因为它可以帮助我们专注于手头的问题,而不是担心很多设置。 对于裸 React Native 应用程序,可以遵循本文中完全相同的步骤。

您需要熟悉JavaScript 和 React Native才能完成本教程。 以下是您应该已经熟悉的一些重要事项:

  • React Native 中的自定义组件(如何在组件中创建组件、接收、传递和使用 props)。 阅读更多。
  • 反应导航。 阅读更多。
  • React Native 中的堆栈导航器。 阅读更多。
  • React Native Core 组件( <View/><Text/>等)的基础知识。 阅读更多。
  • 反应本机AsyncStorage 。 阅读更多。
  • 上下文 API。 阅读更多。

项目设置和基本身份验证

如果您不熟悉 expo 并且不知道如何安装 expo,请访问官方文档。 安装完成后,继续在我们的命令提示符下使用 expo 初始化一个新的 React Native 项目:

 expo init navigation-project

您将看到一些选项来选择您希望基本设置的方式:

React Native 项目的基础设置
(大预览)

在我们的例子中,让我们选择第一个选项将我们的项目设置为空白文档。 现在,等到 JavaScript 依赖项的安装完成。

设置应用程序后,我们可以将目录更改为新项目目录,并在您喜欢的代码编辑器中打开它。 我们需要安装我们将用于AsyncStorage和导航库的库。 在终端的文件夹目录中,粘贴上面的命令并选择一个模板( blank可以)来安装我们的项目依赖项。

让我们看看每个依赖项的用途:

  • @react-native-community/异步存储
    与 web 上的 localStorage 一样,它是一个 React Native API,用于将数据以键值对的形式保存在设备上。
  • @react-native-community/masked-view、react-native-screens、react-native-gesture-handle
    这些依赖项是大多数导航器用来在应用程序中创建导航结构的核心实用程序。 (在 React Native 导航入门中阅读更多内容。)
  • @react-导航/本机
    这是 React Native 导航的依赖项。
  • @反应导航/堆栈
    这是 React Native 中堆栈导航的依赖项。
 npm install @react-native-community/async-storage @react-native-community/masked-view @react-navigation/native @react-navigation/stack react-native-screens react-native-gesture-handle

要启动应用程序,请从终端中的 app 目录使用expo start 。 应用程序启动后,您可以使用手机中的expo应用程序扫描条形码并查看应用程序,或者如果您有android模拟器/IOS模拟器,您可以从expo开发者工具中通过它们打开应用程序。当您启动一个 expo 应用程序时,会在您的浏览器中打开。 对于本文中的图像示例,我们将使用 Genymotions 来查看我们的结果。 以下是我们在 Genymotions 中的最终结果:

Genymotions 中的最终结果
(大预览)

文件夹结构

让我们从一开始就创建我们的文件夹结构,以便我们在继续进行时更容易使用它:

我们首先需要两个文件夹:

  • 语境
    这个文件夹将保存我们整个应用程序的上下文,因为我们将使用 Context API 进行全局状态管理。
  • 意见
    此文件夹将包含导航文件夹和不同屏幕的视图。

继续并在您的项目目录中创建两个文件夹。

在 context 文件夹中,创建一个名为authContext的文件夹,并在authContext文件夹中创建两个文件:

  • AuthContext.js ,
  • AuthState.js

当我们开始使用 Context API 时,我们将需要这些文件。

现在转到我们创建的视图文件夹并在其中创建另外两个文件夹,即:

  • 导航
  • 屏幕

现在,我们还没有完成,在屏幕文件夹中,再创建这两个文件夹:

  • postAuthScreens ,
  • preAuthScreens

如果您正确地遵循了文件夹设置,那么您的文件夹结构现在应该是这样的:

文件夹结构
(大预览)
跳跃后更多! 继续往下看↓

创建我们的第一个屏幕

现在让我们创建第一个屏幕并将其命名preAuthScreens 文件夹中的 welcomeScreen.js

preAuthScreens > welcomeScreen.js

这是我们welcomeScreen.js文件的内容:

 import React from 'react'; import { View, Text, Button, StyleSheet, TextInput } from 'react-native'; const WelcomeScreen = () => { const onUserAuthentication = () => { console.log("User authentication button clicked") } return ( <View style={styles.container}> <Text style={styles.header}>Welcome to our App!</Text> <View> <TextInput style={styles.inputs} placeholder="Enter your email here.." /> <TextInput style={styles.inputs} secureTextEntry={true} placeholder="Enter your password here.." /> <Button title="AUTHENTICATE" onPress={onUserAuthentication} /> </View> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, header: { fontSize: 25, fontWeight: 'bold', marginBottom: 30 }, inputs: { width: 300, height: 40, marginBottom: 10, borderWidth: 1, } }) export default WelcomeScreen

这是我们在上面的代码块中所做的:

首先,我们从 React Native 库中导入我们需要的东西,即ViewTextButtonTextInput 。 接下来,我们创建了我们的功能组件WelcomeScreen

你会注意到我们从 React Native 中导入了StyleSheet ,并用它来定义我们的 header 和<TextInput />的样式。

最后,我们在代码底部导出WelcomeScreen组件。

现在我们已经完成了这个,让我们通过使用useState挂钩来存储输入的值并在输入字段发生更改时更新它们的状态,让这个组件按预期运行。 我们还将从 React 引入useCallback钩子,因为稍后我们将需要它来保存一个函数。

首先,当我们还在WelcomeScreen组件中时,我们需要从 React 中导入useStateuseCallback

 import React, { useState, useCallback } from 'react';

现在在WelcomeScreen功能组件中,让我们分别为电子邮件和密码创建两种状态:

 ... const WelcomeScreen = () => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') return ( ... ) } ...

接下来,我们需要修改我们的<TextInput />字段,以便从它们各自的状态中获取它们的值,并在输入值更新时更新它们的状态:

 import React, { useState, useCallback } from 'react'; import { View, Text, Button, StyleSheet, TextInput } from 'react-native'; const WelcomeScreen = () => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const onInputChange = (value, setState) => { setState(value); } return ( <View> ... <View> <TextInput style={styles.inputs} placeholder="Enter your email here.." value={email} onChangeText={(value) => onInputChange(value, setEmail)} /> <TextInput style={styles.inputs} secureTextEntry={true} placeholder="Enter your password here.." value={password} onChangeText={(value) => onInputChange(value, setPassword)} /> ... </View> </View> ) } ...

在上面的代码中,这是我们所做的:

  • 我们使每个文本输入的value指向它们各自的状态。
  • 我们将onChangeText处理程序添加到我们的文本输入中。 每当从输入字段中输入或删除新值时,都会触发此操作。
  • 我们调用了onInputChange函数,它接受两个参数:
    • 当前valueonChangeText处理程序提供。
    • 应该更新的状态的设置器(对于第一个输入字段,我们通过setEmail和第二个我们通过setPassword
    • 最后,我们编写onInputChange函数,我们的函数只做一件事:用新值更新各自的状态。

接下来我们需要处理的是onUserAuthentication()函数,只要单击表单提交的按钮,就会调用该函数。

理想情况下,用户必须已经创建了一个帐户,并且登录将涉及某种后端逻辑,以检查用户是否存在,然后将令牌分配给用户。 在我们的例子中,由于我们没有使用任何后端,我们将创建一个包含正确用户登录详细信息的对象,然后仅在用户输入的值与我们将要的emailpassword登录对象中的固定值匹配时对用户进行身份验证创建。

这是我们需要执行此操作的代码:

 ... const correctAuthenticationDetails = { email: '[email protected]', password: 'password' } const WelcomeScreen = () => { ... // This function gets called when the `AUTHENTICATE` button is clicked const onUserAuthentication = () => { if ( email !== correctAuthenticationDetails.email || password !== correctAuthenticationDetails.password ) { alert('The email or password is incorrect') return } // In here, we will handle what happens if the login details are // correct } ... return ( ... ) } ...

您将在上面的代码中注意到的第一件事是我们在WelcomeScreen()功能组件之外定义了一个正确的correctAuthenticationDetails (它是一个包含我们希望用户提供的正确登录详细信息的对象)。

接下来,我们编写了onUserAuthentication()函数的内容,并使用条件语句来检查在各自状态下保存的emailpassword是否与我们在对象中提供的不匹配。

如果您想看看我们到目前为止所做的工作,请将WelcomeScreen组件导入到您的App.js 中,如下所示:

打开App.js文件并将整个代码替换为:

 import { StatusBar } from 'expo-status-bar'; import React from 'react'; import { View } from 'react-native'; import WelcomeScreen from './views/screens/preAuthScreens/welcomeScreen'; export default function App() { return ( <View> <StatusBar /> <WelcomeScreen /> </View> ); }

仔细查看上面的代码,您会发现我们所做的是导入WelcomeScreen组件,然后在App()函数中使用它。

以下是我们的WelcomeScreen的结果:

WelcomeScreen 的结果
(大预览)

现在我们已经完成了WelcomeScreen组件的构建,让我们继续并开始使用 Context API 来管理我们的全局状态。

为什么选择上下文 API?

使用 Context API,我们不需要在 ReactJS 中安装任何额外的库,设置压力较小,并且是 ReactJS 中处理全局状态的最流行的方式之一。 对于轻量级的状态管理来说,是一个不错的选择。

创建我们的上下文

如果您还记得,我们之前创建了一个上下文文件夹,并在其中创建了一个名为authContext的子文件夹。

现在让我们导航到authContext文件夹中的AuthContext.js文件并创建我们的上下文:

上下文 > authContext > AuthContext.js

 import React, { createContext } from 'react'; const AuthContext = createContext(); export default AuthContext;

我们刚刚创建的AuthContext保存了loading状态值和userToken状态值。 目前,在我们在上面的代码块中声明的createContext中,我们没有在这里初始化任何默认值,因此我们的上下文当前是undefined 。 auth 上下文的示例值可以是{loading: false, userToken: 'abcd}

AuthState.js文件包含我们的上下文 API 逻辑及其状态值。 此处编写的函数可以从我们应用程序的任何位置调用,当它们更新 state 中的值时,它也会全局更新。

首先,让我们在这个文件中引入我们需要的所有导入:

上下文 > AuthContext > AuthState.js

 import React, { useState } from 'react'; import AuthContext from './AuthContext'; import AsyncStorage from '@react-native-community/async-storage';

我们从 ReactJS 中导入了useState()钩子来保存我们的状态,我们导入了我们在上面创建的AuthContext文件,因为这是我们用于身份验证的空上下文被初始化的地方,我们需要使用它,稍后我们会继续进行,最后我们导入AsyncStorage包(类似于 web 的 localStorage)。

AsyncStorage是一个 React Native API,它允许您在 React Native 应用程序中通过设备离线保存数据。

 ... const AuthState = (props) => { const [userToken, setUserToken] = useState(null); const [isLoading, setIsLoading] = useState(true); const onAuthentication = async() => { const USER_TOKEN = "drix1123q2" await AsyncStorage.setItem('user-token', USER_TOKEN); setUserToken(USER_TOKEN); console.warn("user has been authenticated!") } return ( <AuthContext.Provider value={{ onAuthentication, }} > {props.children} </AuthContext.Provider> ) } export default AuthState;

在上面的代码块中,这是我们所做的:

  • 我们为userTokenisLoading声明了两种状态。 userToken状态将用于存储保存到AsyncStorage的令牌,而isLoading状态将用于跟踪加载状态(最初设置为true )。 随着我们的进行,我们将进一步了解这两种状态的使用。

  • 接下来,我们编写了onAuthentication()函数。 该函数是一个async函数,当从welcomeScreen.jsx文件中单击登录按钮时会调用该函数。 只有当用户提供的电子邮件和密码与我们提供的正确用户详细信息对象匹配时,才会调用此函数。 通常在身份验证期间发生的情况是,用户在后端使用 JWT 之类的包进行身份验证后,会为用户生成一个令牌,并将此令牌发送到前端。 由于我们不会在本教程中介绍所有这些内容,因此我们创建了一个静态令牌并将其保存在一个名为USER_TOKEN的变量中。

  • 接下来,我们使用await关键字将我们的用户令牌设置为 AsyncStorage,名称为user-tokenconsole.warn()语句仅用于检查一切是否正常,您可以随时将其取下。

  • 最后,我们将onAuthenticated函数作为值传递到<AuthContext.Provider>中,以便我们可以从应用程序中的任何位置访问和调用该函数。

屏幕 > preAuth > welcomeScreen.js

首先,从 ReactJS 中导入useContext并从AuthContext.js文件中导入AuthContext

 import React, { useState, useContext } from 'react'; import AuthContext from '../../../context/authContext/AuthContext' ...

现在,在welcomeScreen()功能组件中,让我们使用我们创建的上下文:

 ... const WelcomeScreen = () => { const { onAuthentication } = useContext(AuthContext) const onUserAuthentication = () => { if ( email !== correctAuthenticationDetails.email || password !== correctAuthenticationDetails.password ) { alert('The email or password is incorrect') return } onAuthentication() } return ( ... ) } ...

在上面的代码块中,我们从AuthContext onAuthentication ,然后我们在onUserAuthentication()函数中调用它,并删除了之前存在的console.log()语句。

现在,这将引发错误,因为我们还没有访问AuthContext的权限。 要在应用程序的任何地方使用AuthContext ,我们需要使用AuthState包装应用程序中的顶级文件(在我们的示例中,它是App.js文件)。

转到App.js文件并将那里的代码替换为:

 import React from 'react'; import WelcomeScreen from './views/screens/preAuthScreens/welcomeScreen'; import AuthState from './context/authContext/AuthState' export default function App() { return ( <AuthState> <WelcomeScreen /> </AuthState> ); }

到目前为止,我们已经完成了本节。 在我们进入下一部分设置路由之前,让我们创建一个新屏幕。 我们即将创建的屏幕将是HomeScreen.js文件,该文件应该仅在成功验证后才会显示。

转到:屏幕 > postAuth

创建一个名为HomeScreen.js的新文件。 这是HomeScreen.js文件的代码:

屏幕 > postAuth > HomeScreen.js

 import React from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; const HomeScreen = () => { const onLogout = () => { console.warn("Logout button cliked") } return ( <View style={styles.container}> <Text>Now you're authenticated! Welcome!</Text> <Button title="LOG OUT" onPress={onLogout} /> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, }) export default HomeScreen

目前,注销按钮有一个虚拟的console.log()语句。 稍后,我们将创建注销功能并将其从我们的上下文传递到屏幕。

设置我们的路线

我们需要在导航文件夹中创建三 (3) 个文件:

  • postAuthNavigator.js ,
  • preAuthNavigator.js ,
  • 应用导航器.js

创建这三个文件后,导航到您刚刚创建的preAuthNaviagtor.js文件并编写以下代码:

导航 > preAuthNavigator.js

 import React from "react"; import { createStackNavigator } from "@react-navigation/stack"; import WelcomeScreen from "../screens/preAuthScreens/welcomeScreen"; const PreAuthNavigator = () => { const { Navigator, Screen } = createStackNavigator(); return ( <Navigator initialRouteName="Welcome"> <Screen name="Welcome" component={WelcomeScreen} /> </Navigator> ) } export default PreAuthNavigator;

在上面的文件中,这是我们所做的:

  • 我们从用于堆栈导航的@react-navigation/stack中导入了createStackNavigatorcreateStackNavigator为您的应用程序提供一种在屏幕之间转换的方法,其中每个新屏幕都放置在堆栈顶部。 默认情况下,堆栈导航器配置为具有熟悉的 iOS 和 Android 外观:新屏幕在 iOS 上从右侧滑入,在 Android 上从底部淡入。 如果您想了解有关 React Native 中堆栈导航器的更多信息,请单击此处。
  • 我们从createStackNavigator()解构了NavigatorScreen
  • 在我们的返回语句中,我们使用<Navigator/>创建了导航,并使用<Screen/>创建了屏幕。 这意味着如果我们有多个可以在身份验证之前访问的屏幕,我们将在此处有多个<Screen/>标签来表示它们。
  • 最后,我们导出PreAuthNavigator组件。

让我们对postAuthNavigator.js文件做类似的事情。

导航 > postAuthNavigator.js

 import React from "react"; import { createStackNavigator } from "@react-navigation/stack"; import HomeScreen from "../screens/postAuthScreens/HomeScreen"; const PostAuthNavigator = () => { const { Navigator, Screen} = createStackNavigator(); return ( <Navigator initialRouteName="Home"> <Screen name="Home" component={HomeScreen} /> </Navigator> ) } export default PostAuthNavigator;

正如我们在上面的代码中看到的, preAuthNavigator.jspostAuthNavigator.js之间的唯一区别是正在渲染的屏幕。 第一个采用WelcomeScreen ,而postAuthNavigator.js采用HomeScreen

要创建我们的AppNavigator.js ,我们需要创建一些东西。

由于AppNavigator.js是我们将切换并检查哪些路由可供用户访问的地方,因此我们需要几个屏幕才能正常工作,让我们先概述一下我们需要创建的内容:

  1. 过渡屏幕.js
    当应用程序决定要安装哪个导航时,我们希望显示一个过渡屏幕。 通常,过渡屏幕将是加载微调器或为应用程序选择的任何其他自定义动画,但在我们的例子中,我们将使用基本的<Text/>标签来显示loading…
  2. checkAuthenticationStatus()
    我们将调用此函数来检查身份验证状态,这将确定要挂载的导航堆栈。 我们将在我们的上下文中创建这个函数并在Appnavigator.js中使用它。

现在,让我们继续创建我们的TransitionScreen.js文件。

屏幕 > TransitionScreen.js

 import React from 'react'; import { Text, View } from 'react-native'; const TransitionScreen = () => { return ( <View> <Text>Loading...</Text> </View> ) } export default TransitionScreen

我们的过渡屏幕只是一个显示加载文本的简单屏幕。 在本文继续进行时,我们将看到在哪里使用它。

接下来,让我们转到AuthState.js并编写我们的checkAuthenticationStatus()

上下文 > authContext > AuthState.js

 import React, { useState, useEffect } from 'react'; import AuthContext from './AuthContext'; import AsyncStorage from '@react-native-community/async-storage'; const AuthState = (props) => { const [userToken, setUserToken] = useState(null); const [isLoading, setIsLoading] = useState(true); ... useEffect(() => { checkAuthenticationStatus() }, []) const checkAuthenticationStatus = async () => { try { const returnedToken = await AsyncStorage.getItem('user-toke n'); setUserToken(returnedToken); console.warn('User token set to the state value) } catch(err){ console.warn(`Here's the error that occured while retrievin g token: ${err}`) } setIsLoading(false) } const onAuthentication = async() => { ... } return ( <AuthContext.Provider value={{ onAuthentication, userToken, isLoading, }} > {props.children} </AuthContext.Provider> ) } export default AuthState;

在上面的代码块中,我们编写了函数checkAuthenticationStatus() 。 在我们的函数中,我们正在执行以下操作:

  • 我们使用await关键字从AsyncStorage获取我们的令牌。 使用AsyncStorage ,如果没有提供令牌,则返回null 。 我们的初始userToken状态也设置为null
  • 我们使用setUserTokenAsyncStorage返回的值设置为新的userToken 。 如果返回值为null ,则表示我们的userToken保持为null
  • try{}…catch(){}块之后,我们将isLoading设置为 false,因为检查身份验证状态的功能已完成。 我们需要isLoading的值来知道我们是否仍然应该显示TransitionScreen 。 如果在检索令牌时出现错误,则值得考虑设置错误,以便在遇到错误时向用户显示“重试”或“重试”按钮。
  • 每当AuthState挂载时,我们都想检查身份验证状态,因此我们使用useEffect() ReactJS 挂钩来执行此操作。 我们在useEffect()钩子中调用我们的checkAuthenticationStatus()函数,并在完成时将isLoading的值设置为false
  • 最后,我们将状态添加到我们的<AuthContext.Provider/>值中,以便我们可以从 Context API 覆盖的应用程序中的任何位置访问它们。

现在我们有了函数,是时候回到我们的AppNavigator.js并编写代码以根据身份验证状态挂载特定的堆栈导航器:

导航 > AppNavigator.js

首先,我们将导入AppNavigator.js所需的所有内容。

 import React, { useEffect, useContext } from "react"; import PreAuthNavigator from "./preAuthNavigator"; import PostAuthNavigator from "./postAuthNavigator"; import { NavigationContainer } from "@react-navigation/native" import { createStackNavigator } from "@react-navigation/stack"; import AuthContext from "../../context/authContext/AuthContext"; import TransitionScreen from "../screens/TransitionScreen";

现在我们有了所有的导入,让我们创建AppNavigator()函数。

 ... const AppNavigator = () => { } export default AppNavigator

接下来,我们现在继续编写AppNavigator()函数的内容:

 import React, { useState, useEffect, useContext } from "react"; import PreAuthNavigator from "./preAuthNavigator"; import PostAuthNavigator from "./postAuthNavigator"; import { NavigationContainer } from "@react-navigation/native" import { createStackNavigator } from "@react-navigation/stack"; import AuthContext from "../../context/authContext/AuthContext"; import TransitionScreen from "../screens/transition"; const AppNavigator = () => { const { Navigator, Screen } = createStackNavigator(); const authContext = useContext(AuthContext); const { userToken, isLoading } = authContext; if(isLoading) { return <TransitionScreen /> } return ( <NavigationContainer> <Navigator> { userToken == null ? ( <Screen name="PreAuth" component={PreAuthNavigator} options={{ header: () => null }} /> ) : ( <Screen name="PostAuth" component={PostAuthNavigator} options={{ header: () => null }} /> ) } </Navigator> </NavigationContainer> ) } export default AppNavigator

在上面的代码块中,以下是我们所做工作的概要:

  • 我们创建了一个堆栈导航器并从中解构了NavigatorScreen
  • 我们从AuthContext导入了userTokenisLoading
  • AuthState挂载时, checkAuthenticationStatus()useEffecct钩子中被调用。 我们使用if语句检查isLoading是否为true ,如果为true ,我们返回的屏幕是我们之前创建的<TransitionScreen /> ,因为checkAuthenticationStatus()函数尚未完成。
  • 一旦我们的checkAuthenticationStatus()完成, isLoading被设置为false并且我们返回我们的主要导航组件。
  • NavigationContainer是从@react-navigation/native导入的。 它仅在主顶级导航器中使用一次。 请注意,我们没有在preAuthNavigator.jspostAuthNavigator.js 中使用它。
  • 在我们的AppNavigator()中,我们仍然创建了一个堆栈导航器。 如果从我们的 Context API 获取的userTokennull ,我们挂载PreAuthNavigator ,如果它的值是其他值(意味着AsyncStorage.getItem()中的checkAuthenticationStatus()返回一个实际值),那么我们挂载PostAuthNavigator 。 我们的条件渲染是使用三元运算符完成的。

现在我们已经设置了AppNavigator.js 。 接下来,我们需要将AppNavigator传递到App.js文件中。

让我们将AppNavigator传递到App.js文件中:

应用程序.js

 ... import AppNavigator from './views/navigation/AppNavigator'; ... return ( <AuthState> <AppNavigator /> </AuthState> );

现在让我们看看我们的应用程序现在的样子:

当您在尝试登录时提供不正确的凭据时,会发生以下情况:

添加注销功能

至此,我们的鉴权和选路过程就完成了。 我们的应用程序唯一剩下的就是添加注销功能。

注销按钮位于HomeScreen.js文件中。 我们将onLogout()函数传递给按钮的onPress属性。 目前,我们的函数中有一个简单的console.log()语句,但过一会儿就会改变。

现在,让我们转到AuthState.js并编写注销函数。 此函数只是清除保存用户令牌的AsyncStorage

上下文 > authContext > AuthState.js

 ... const AuthState = (props) => { ... const userSignout = async() => { await AsyncStorage.removeItem('user-token'); setUserToken(null); } return ( ... ) } export default AuthState;

userSignout()是一个异步函数,它从我们的AsyncStorage中删除user-token

现在我们需要在点击注销按钮的任何时候调用HomeScreen.js中的userSignout()函数。

让我们转到HomeScreen.js并使用 AuthContext 中的AuthContext userSignout()

屏幕 > postAuthScreens > HomeScreen.js

 import React, { useContext } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; import AuthContext from '../../../context/authContext/AuthContext' const HomeScreen = () => { const { userSignout } = useContext(AuthContext) const onLogout = () => { userSignout() } return ( <View style={styles.container}> <Text>Now you're authenticated! Welcome!</Text> <Button title="LOG OUT" onPress={onLogout} /> </View> ) } ...

在上面的代码块中,我们从 ReactJS 中导入了useContext钩子,然后我们导入了 AuthContext。 接下来,我们从AuthContext中解构userSignout函数,并在userSignout()函数中调用这个onLogout()函数。

现在,只要单击我们的注销按钮,我们的AsyncStorage中的用户令牌就会被清除。

瞧! 我们的整个过程就完成了。

登录后按返回按钮时会发生以下情况:

登录应用程序后按返回按钮。

注销后按返回按钮时会发生以下情况:

退出应用程序后按返回按钮。

以下是我们在导航堆栈切换中使用此模式时注意到的一些不同行为:

  1. 你会注意到登录后我们不需要使用navigation.navigate()navigation.push()去另一条路线。 使用用户令牌更新我们的状态后,呈现的导航堆栈会自动更改。
  2. 登录成功后按设备上的返回按钮无法返回登录页面,而是完全关闭应用程序。 此行为很重要,因为您不希望用户能够返回登录页面,除非他们退出应用程序。 同样的事情也适用于注销——一旦用户注销,他们就不能使用后退按钮返回主HomeScreen屏幕,而是关闭应用程序。

结论

在许多应用程序中,身份验证是最重要的部分之一,因为它确认试图访问受保护内容的人有权访问信息。 学习如何正确操作是构建出色、直观且易于使用/导航的应用程序的重要一步。

在此代码之上,您可能会考虑添加以下内容:

  • 用于验证输入字段的表单验证。 查看使用 Formik 和 Yup 进行 React Native 表单验证。
  • Firebase 身份验证,用于将身份验证与 Gmail、Github、Facebook、Twitter 或您的自定义界面集成。 查看 React Native Firebase。
  • 设计人员的代码概念:身份验证和授权。

这里还有一些我发现的重要资源,它们可以让您更多地了解身份验证、安全性以及如何正确操作:

资源

  • React Native:解释用户身份验证流程
  • 10 个 React 安全最佳实践
  • 可以防止下一次违规的身份验证方法
  • 在此处查看我们应用程序的实时构建/预览;
  • 在 GitHub 上查看项目。