在 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 上查看項目。