Umgang mit dem Mounten und Unmounten von Navigationsrouten in React Native
Veröffentlicht: 2022-03-10In diesem Artikel gehen wir durch das Mounten und Unmounten von Navigationsrouten in React Native. Ein erwartetes Verhalten Ihrer App ist, dass sobald die Authentifizierungsbedingung erfüllt ist, ein neuer Satz von Navigationsrouten nur für angemeldete Benutzer verfügbar ist, während die anderen Bildschirme, die vor der Authentifizierung angezeigt wurden, entfernt werden und nicht zu ihnen zurückkehren können, es sei denn Benutzer meldet sich von der Anwendung ab.
Für die Sicherheit in Ihrer App bieten Ihnen geschützte Routen die Möglichkeit, bestimmte Informationen/Inhalte in Ihrer App nur bestimmten Benutzern anzuzeigen und gleichzeitig den Zugriff für Unbefugte einzuschränken.
Wir werden für dieses Projekt mit Expo zusammenarbeiten, weil es uns hilft, uns auf das vorliegende Problem zu konzentrieren, anstatt uns um viele Einstellungen zu kümmern. Die exakt gleichen Schritte in diesem Artikel könnten für eine bloße React Native-Anwendung befolgt werden.
Sie müssen mit JavaScript und React Native vertraut sein, um dieses Tutorial durchzuarbeiten. Hier sind ein paar wichtige Dinge, mit denen Sie bereits vertraut sein sollten:
- Benutzerdefinierte Komponenten in React Native (wie man Komponenten erstellt, Requisiten in einer Komponente empfängt, weitergibt und verwendet). Weiterlesen.
- Reagieren Sie auf die Navigation. Weiterlesen.
- Stack-Navigator in React Native. Weiterlesen.
- Grundkenntnisse der React Native Core-Komponenten (
<View/>
,<Text/>
, etc.). Weiterlesen. - Reagieren
AsyncStorage
. Weiterlesen. - Kontext-API. Weiterlesen.
Projekteinrichtung und Basisauthentifizierung
Wenn Sie neu in der Verwendung von Expo sind und nicht wissen, wie Expo installiert wird, besuchen Sie die offizielle Dokumentation. Sobald die Installation abgeschlossen ist, initialisieren Sie ein neues React Native-Projekt mit Expo von unserer Eingabeaufforderung aus:
expo init navigation-project
Ihnen werden einige Optionen angezeigt, mit denen Sie auswählen können, wie das Basis-Setup aussehen soll:
Wählen wir in unserem Fall die erste Option, um unser Projekt als leeres Dokument einzurichten. Warten Sie nun, bis die Installation der JavaScript-Abhängigkeiten abgeschlossen ist.
Sobald unsere App eingerichtet ist, können wir unser Verzeichnis in unser neues Projektverzeichnis ändern und es in Ihrem bevorzugten Code-Editor öffnen. Wir müssen die Bibliothek installieren, die wir für AsyncStorage
und unsere Navigationsbibliotheken verwenden werden. Fügen Sie in Ihrem Ordnerverzeichnis in Ihrem Terminal den obigen Befehl ein und wählen Sie eine Vorlage ( blank
würde funktionieren), um unsere Projektabhängigkeiten zu installieren.
Schauen wir uns an, wofür jede dieser Abhängigkeiten ist:
- @react-native-community/async-storage
Wie localStorage im Web ist es eine React Native API, um Daten auf einem Gerät in Schlüssel-Wert-Paaren zu speichern. - @React-Native-Community/Masked-View, React-Native-Screens, React-Native-Gesture-Handle
Diese Abhängigkeiten sind zentrale Dienstprogramme, die von den meisten Navigatoren verwendet werden, um die Navigationsstruktur in der App zu erstellen. (Lesen Sie mehr unter Erste Schritte mit der React Native-Navigation.) - @react-navigation/native
Dies ist die Abhängigkeit für die React Native-Navigation. - @react-navigation/stack
Dies ist die Abhängigkeit für die Stack-Navigation in 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
Um die Anwendung zu starten, verwenden Sie expo start
aus dem App-Verzeichnis in Ihrem Terminal. Sobald die App gestartet ist, können Sie die Expo-App von Ihrem Mobiltelefon aus verwenden, um den Barcode zu scannen und die Anwendung anzuzeigen, oder wenn Sie einen Android-Emulator/IOS-Simulator haben, können Sie die App über das Expo-Entwicklertool öffnen öffnet sich in Ihrem Browser, wenn Sie eine Expo-Anwendung starten. Für die Bildbeispiele in diesem Artikel verwenden wir Genymotions, um unser Ergebnis zu sehen. So wird unser Endergebnis in Genymotions aussehen:
Ordnerstrukturen
Lassen Sie uns unsere Ordnerstruktur von Anfang an erstellen, damit wir im weiteren Verlauf einfacher damit arbeiten können:
Wir brauchen zuerst zwei Ordner:
- Kontext
Dieser Ordner enthält den Kontext für unsere gesamte Anwendung, da wir mit der Kontext-API für die globale Zustandsverwaltung arbeiten werden. - Ansichten
Dieser Ordner enthält sowohl den Navigationsordner als auch die Ansichten für verschiedene Bildschirme.
Fahren Sie fort und erstellen Sie die beiden Ordner in Ihrem Projektverzeichnis.
Erstellen Sie im Kontextordner einen Ordner mit dem Namen authContext und erstellen Sie zwei Dateien im Ordner authContext :
- AuthContext.js ,
- AuthState.js .
Wir benötigen diese Dateien, wenn wir anfangen, mit der Kontext-API zu arbeiten.
Gehen Sie nun zu dem von uns erstellten Ordner views und erstellen Sie darin zwei weitere Ordner, nämlich:
- Navigation ,
- Bildschirme .
Jetzt sind wir noch nicht fertig, erstellen Sie im Bildschirmordner diese beiden weiteren Ordner:
- postAuthScreens ,
- preAuthScreens .
Wenn Sie die Ordnereinrichtung korrekt durchgeführt haben, sollte Ihre Ordnerstruktur im Moment so aussehen:
Erstellen unseres ersten Bildschirms
Lassen Sie uns nun unseren ersten Bildschirm erstellen und ihn im Ordner „ preAuthScreens “ „ welcomeScreen.js “ nennen.
preAuthScreens > welcomeScreen.js
Hier ist der Inhalt unserer Datei 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
Folgendes haben wir im obigen Codeblock getan:
Zuerst haben wir die Dinge, die wir brauchen, aus der React Native-Bibliothek importiert, nämlich View
, Text
, Button
, TextInput
. Als nächstes haben wir unsere funktionale Komponente WelcomeScreen
.
Sie werden feststellen, dass wir das StyleSheet
von React Native importiert und es verwendet haben, um Stile für unseren Header und auch unseren <TextInput />
zu definieren.
Zuletzt exportieren wir die WelcomeScreen
Komponente am Ende des Codes.
Nachdem wir damit fertig sind, wollen wir diese Komponente dazu bringen, wie erwartet zu funktionieren, indem wir den useState
Hook verwenden, um die Werte der Eingaben zu speichern und ihre Zustände jedes Mal zu aktualisieren, wenn eine Änderung in den Eingabefeldern auftritt. Wir werden auch den useCallback
Hook von React importieren, da wir ihn später benötigen werden, um eine Funktion zu halten.
Zunächst müssen wir, während wir uns noch in der WelcomeScreen
Komponente befinden, useState
und useCallback
von React importieren.
import React, { useState, useCallback } from 'react';
Lassen Sie uns nun in der Funktionskomponente WelcomeScreen
die beiden Zustände für die E-Mail bzw. das Passwort erstellen:
... const WelcomeScreen = () => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') return ( ... ) } ...
Als Nächstes müssen wir unsere <TextInput />
Felder so ändern, dass sie ihren Wert aus ihren jeweiligen Zuständen erhalten und ihren Zustand aktualisieren, wenn der Wert der Eingabe aktualisiert wird:
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> ) } ...
Im obigen Code haben wir Folgendes getan:
- Wir haben den
value
jeder der Texteingaben so gemacht, dass sie auf ihre jeweiligen Zustände zeigen. - Wir haben den Handler
onChangeText
zu unseren Texteingaben hinzugefügt. Dies wird immer dann ausgelöst, wenn ein neuer Wert in die Eingabefelder eingegeben oder gelöscht wird. - Wir haben unsere
onInputChange
Funktion aufgerufen, die zwei Argumente akzeptiert:- Der aktuelle
value
wird vomonChangeText
Handler bereitgestellt. - Der Setter des Zustands, der aktualisiert werden soll (für das erste Eingabefeld übergeben wir
setEmail
und für das zweite übergeben wirsetPassword
. - Schließlich schreiben wir unsere
onInputChange
Funktion, und unsere Funktion macht nur eines: Sie aktualisiert die jeweiligen Zustände mit dem neuen Wert.
- Der aktuelle
Das nächste, woran wir arbeiten müssen, ist die Funktion onUserAuthentication()
, die immer dann aufgerufen wird, wenn auf die Schaltfläche zum Senden des Formulars geklickt wird.
Im Idealfall muss der Benutzer bereits ein Konto erstellt haben, und die Anmeldung erfordert eine Art Backend-Logik, um zu überprüfen, ob der Benutzer existiert, und ihm dann ein Token zuzuweisen. Da wir in unserem Fall kein Backend verwenden, erstellen wir ein Objekt, das die korrekten Anmeldedaten des Benutzers enthält, und authentifizieren dann einen Benutzer nur, wenn die von ihm eingegebenen Werte mit unseren festen Werten aus dem von uns festgelegten Anmeldeobjekt von email
und password
übereinstimmen schaffen.
Hier ist der Code, den wir dafür brauchen:
... 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 ( ... ) } ...
Eines der ersten Dinge, die Sie im obigen Code bemerken werden, ist, dass wir ein correctAuthenticationDetails
(ein Objekt, das die korrekten Anmeldedaten enthält, die wir von einem Benutzer erwarten) außerhalb der Funktionskomponente WelcomeScreen()
.
Als nächstes haben wir den Inhalt der Funktion onUserAuthentication()
und eine bedingte Anweisung verwendet, um zu prüfen, ob die email
-Adresse oder das password
in den jeweiligen Zuständen nicht mit denen übereinstimmen, die wir in unserem Objekt angegeben haben.
Wenn Sie sehen möchten, was wir bisher gemacht haben, importieren Sie die WelcomeScreen- Komponente wie folgt in Ihre App.js :
Öffnen Sie die App.js -Datei und ersetzen Sie den gesamten Code durch diesen:
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> ); }
Wenn Sie sich den Code oben genau ansehen, werden Sie sehen, dass wir die WelcomeScreen- Komponente importiert und dann in der App()
Funktion verwendet haben.
So sieht das Ergebnis unseres WelcomeScreen
aus:
Nachdem wir nun die WelcomeScreen -Komponente erstellt haben, können wir weitermachen und mit der Kontext-API arbeiten, um unseren globalen Status zu verwalten.
Warum Kontext-API?
Durch die Verwendung der Kontext-API müssen wir keine zusätzliche Bibliothek in ReactJS installieren, die Einrichtung ist weniger stressig und eine der beliebtesten Methoden zum Umgang mit dem globalen Zustand in ReactJS. Für eine einfache Zustandsverwaltung ist dies eine gute Wahl.
Unseren Kontext schaffen
Wenn Sie sich erinnern, haben wir zuvor einen Kontextordner erstellt und darin einen Unterordner mit dem Namen authContext erstellt .
Navigieren wir nun zur Datei AuthContext.js im Ordner authContext und erstellen unseren Kontext:
Kontext > authContext > AuthContext.js
import React, { createContext } from 'react'; const AuthContext = createContext(); export default AuthContext;
Der gerade erstellte AuthContext
enthält den loading
und die userToken
-Zustandswerte. Derzeit haben wir im createContext
, den wir im obigen Codeblock deklariert haben, hier keine Standardwerte initialisiert, sodass unser Kontext derzeit undefined
ist. Ein Beispielwert des Authentifizierungskontexts könnte {loading: false, userToken: 'abcd}
Die Datei AuthState.js enthält unsere Kontext-API-Logik und ihre Zustandswerte. Hier geschriebene Funktionen können von überall in unserer App aufgerufen werden, und wenn sie Werte im Status aktualisieren, werden sie auch global aktualisiert.
Lassen Sie uns zunächst alle Importe, die wir benötigen, in diese Datei einfügen:
Kontext > AuthContext > AuthState.js
import React, { useState } from 'react'; import AuthContext from './AuthContext'; import AsyncStorage from '@react-native-community/async-storage';
Wir haben den useState()
Hook von ReactJS importiert, um unsere Zustände zu speichern, wir haben die AuthContext -Datei importiert, die wir oben erstellt haben, weil hier unser leerer Kontext für die Authentifizierung initialisiert wird und wir ihn verwenden müssen, wie Sie später sehen werden, während wir fortfahren , schließlich importieren wir das AsyncStorage
-Paket (ähnlich wie localStorage für das Web).
AsyncStorage
ist eine React Native API, mit der Sie Daten offline über das Gerät in einer React Native-Anwendung speichern können.
... 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;
Im obigen Codeblock haben wir Folgendes getan:
Wir haben zwei Zustände für
userToken
undisLoading
. Der ZustanduserToken
wird verwendet, um das inAsyncStorage
gespeicherte Token zu speichern, während der ZustandisLoading
verwendet wird, um den Ladestatus zu verfolgen (ursprünglich ist er auftrue
gesetzt). Wir werden im weiteren Verlauf mehr über die Verwendung dieser beiden Zustände erfahren.Als Nächstes haben wir unsere Funktion
onAuthentication()
. Diese Funktion ist eineasync
Funktion, die aufgerufen wird, wenn in der DateiwelcomeScreen.jsx
auf die Anmeldeschaltfläche geklickt wird. Diese Funktion wird nur aufgerufen, wenn die E-Mail-Adresse und das Passwort, die der Benutzer angegeben hat, mit dem korrekten Benutzerdetailobjekt übereinstimmen, das wir bereitgestellt haben. Normalerweise passiert während der Authentifizierung, dass ein Token für den Benutzer generiert wird, nachdem der Benutzer am Backend mit einem Paket wie JWT authentifiziert wurde, und dieses Token an das Frontend gesendet wird. Da wir in diesem Tutorial nicht auf all das eingehen, haben wir ein statisches Token erstellt und es in einer Variablen namensUSER_TOKEN
.Als Nächstes verwenden wir das Schlüsselwort
await
, um unser Benutzertoken auf AsyncStorage mit dem Namenuser-token
zu setzen. Dieconsole.warn()
wird nur verwendet, um zu überprüfen, ob alles richtig gelaufen ist, Sie können sie jederzeit entfernen.Schließlich übergeben wir unsere
onAuthenticated
Funktion als Wert in unserem<AuthContext.Provider>
, sodass wir von überall in unserer App auf die Funktion zugreifen und sie aufrufen können.
screens > preAuth > welcomeScreen.js
Importieren Sie zunächst useContext
aus ReactJS und importieren Sie den AuthContext
aus der Datei AuthContext.js
.
import React, { useState, useContext } from 'react'; import AuthContext from '../../../context/authContext/AuthContext' ...
Lassen Sie uns nun innerhalb der Funktionskomponente welcomeScreen()
den Kontext verwenden, den wir erstellt haben:
... 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 ( ... ) } ...
Im obigen Codeblock haben wir die onAuthentication
Funktion aus unserem AuthContext
und dann innerhalb unserer onUserAuthentication()
Funktion aufgerufen und die zuvor vorhandene Anweisung console.log()
() entfernt.
Im Moment wird dies einen Fehler auslösen, da wir noch keinen Zugriff auf den AuthContext
haben. Um den AuthContext
überall in Ihrer Anwendung zu verwenden, müssen wir die Datei der obersten Ebene in unserer App mit dem AuthState
(in unserem Fall ist es die App.js -Datei).
Gehen Sie zur Datei App.js und ersetzen Sie den Code dort durch diesen:
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> ); }
Wir sind so weit gekommen und wir sind mit diesem Abschnitt fertig. Bevor wir zum nächsten Abschnitt übergehen, in dem wir unser Routing einrichten, erstellen wir einen neuen Bildschirm. Der Bildschirm, den wir gerade erstellen, ist die Datei HomeScreen.js , die nur nach erfolgreicher Authentifizierung angezeigt werden soll.
Gehen Sie zu: Bildschirme > postAuth .
Erstellen Sie eine neue Datei namens HomeScreen.js . Hier ist der Code für die Datei HomeScreen.js :
screens > 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
Im Moment hat die Abmeldeschaltfläche eine Dummy console.log()
. Später erstellen wir die Abmeldefunktion und übergeben sie aus unserem Kontext an den Bildschirm.
Einrichten unserer Routen
Wir müssen drei (3) Dateien in unserem Navigationsordner erstellen:
- postAuthNavigator.js ,
- preAuthNavigator.js ,
- AppNavigator.js .
Nachdem Sie diese drei Dateien erstellt haben, navigieren Sie zu der gerade erstellten Datei preAuthNavigtor.js und schreiben Sie Folgendes:
navigation > 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;
In der obigen Datei haben wir Folgendes getan:
- Wir haben den
createStackNavigator
aus@react-navigation/stack
importiert, den wir für unsere Stack-Navigation verwenden. DercreateStackNavigator
bietet Ihrer App die Möglichkeit, zwischen Bildschirmen zu wechseln, wobei jeder neue Bildschirm auf einem Stapel platziert wird. Standardmäßig ist der Stack-Navigator so konfiguriert, dass er das vertraute Aussehen und Verhalten von iOS und Android hat: Neue Bildschirme werden bei iOS von rechts eingeschoben, bei Android von unten eingeblendet. Klicken Sie hier, wenn Sie mehr über den Stack-Navigator in React Native erfahren möchten. - Wir haben
Navigator
undScreen
voncreateStackNavigator()
. - In unserer return-Anweisung haben wir unsere Navigation mit dem
<Navigator/>
und unseren Bildschirm mit dem<Screen/>
erstellt. Das bedeutet, dass wir, wenn wir mehrere Bildschirme hatten, auf die vor der Authentifizierung zugegriffen werden kann, hier mehrere<Screen/>
-Tags haben, die sie darstellen. - Schließlich exportieren wir unsere
PreAuthNavigator
Komponente.
Lassen Sie uns etwas Ähnliches für die Datei postAuthNavigator.js
tun.
navigation > 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;
Wie wir im obigen Code sehen, ist der einzige Unterschied zwischen preAuthNavigator.js und postAuthNavigator.js der gerenderte Bildschirm. Während der erste den WelcomeScreen
übernimmt, übernimmt postAuthNavigator.js den HomeScreen
.
Um unsere AppNavigator.js zu erstellen, müssen wir ein paar Dinge erstellen.
Da wir in AppNavigator.js wechseln und prüfen, welche Route für den Zugriff durch den Benutzer verfügbar ist, benötigen wir mehrere Bildschirme, damit dies ordnungsgemäß funktioniert. Lassen Sie uns die Dinge skizzieren, die wir zuerst erstellen müssen:
- TransitionScreen.js
Während die App entscheidet, welche Navigation sie montieren wird, möchten wir, dass ein Übergangsbildschirm angezeigt wird. Normalerweise ist der Übergangsbildschirm ein Lade-Spinner oder eine andere benutzerdefinierte Animation, die für die App ausgewählt wurde, aber in unserem Fall verwenden wir ein einfaches<Text/>
-Tag, um anzuzeigen, dassloading…
. -
checkAuthenticationStatus()
Diese Funktion wird aufgerufen, um den Authentifizierungsstatus zu überprüfen, der bestimmt, welcher Navigationsstapel bereitgestellt wird. Wir werden diese Funktion in unserem Kontext erstellen und in der Appnavigator.js verwenden .
Lassen Sie uns nun fortfahren und unsere TransitionScreen.js -Datei erstellen.
Bildschirme > TransitionScreen.js
import React from 'react'; import { Text, View } from 'react-native'; const TransitionScreen = () => { return ( <View> <Text>Loading...</Text> </View> ) } export default TransitionScreen
Unser Übergangsbildschirm ist nur ein einfacher Bildschirm, der Ladetext anzeigt. Wir werden sehen, wo wir dies verwenden können, wenn wir in diesem Artikel fortfahren.
Als nächstes gehen wir zu unserer AuthState.js und schreiben unsere checkAuthenticationStatus()
:
Kontext > 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;
Im obigen Codeblock haben wir die Funktion checkAuthenticationStatus()
. In unserer Funktion tun wir Folgendes:
- Wir haben das Schlüsselwort
await
verwendet, um unser Token vonAsyncStorage
zu erhalten. Wenn beiAsyncStorage
kein Token bereitgestellt wird, wirdnull
zurückgegeben. Unser anfänglicheruserToken
-Status wird ebenfalls aufnull
gesetzt. - Wir verwenden
setUserToken
, um unseren zurückgegebenen Wert vonAsyncStorage
als unser neuesuserToken
. Wenn der zurückgegebene Wertnull
ist, bedeutet dies, dass unseruserToken
null
bleibt. - Nach dem Block
try{}…catch(){}
setzen wirisLoading
auf false, da die Funktion zum Überprüfen des Authentifizierungsstatus abgeschlossen ist. Wir benötigen den Wert vonisLoading
, um zu wissen, ob wir denTransitionScreen
weiterhin anzeigen sollen oder nicht. Es lohnt sich, einen Fehler festzulegen, wenn beim Abrufen des Tokens ein Fehler auftritt, damit wir dem Benutzer eine Schaltfläche „Wiederholen“ oder „Erneut versuchen“ anzeigen können, wenn der Fehler auftritt. - Immer wenn
AuthState
, möchten wir den Authentifizierungsstatus überprüfen, also verwenden wir dazu denuseEffect()
ReactJS-Hook. Wir rufen unsere FunktioncheckAuthenticationStatus()
innerhalb desuseEffect()
auf und setzen den Wert vonisLoading
auffalse
, wenn es fertig ist. - Schließlich fügen wir unsere Zustände zu unseren
<AuthContext.Provider/>
Werten hinzu, damit wir von überall in unserer App, die von der Kontext-API abgedeckt wird, darauf zugreifen können.
Jetzt, da wir unsere Funktion haben, ist es an der Zeit, zu unserer AppNavigator.js zurückzukehren und den Code zum Mounten eines bestimmten Stack-Navigators basierend auf dem Authentifizierungsstatus zu schreiben:
Navigation > AppNavigator.js
Zuerst importieren wir alles, was wir für unsere AppNavigator.js benötigen.
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";
Nachdem wir nun alle unsere Importe haben, erstellen wir die Funktion AppNavigator()
.
... const AppNavigator = () => { } export default AppNavigator
Als nächstes werden wir nun den Inhalt unserer Funktion AppNavigator()
schreiben:
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
Im obigen Codeblock ist hier ein Überblick darüber, was wir getan haben:
- Wir haben einen Stapelnavigator erstellt und den
Navigator
und denScreen
daraus destrukturiert. - Wir haben das
userToken
und dasisLoading
aus unseremAuthContext
- Wenn der
AuthState
wird, wird dort dercheckAuthenticationStatus()
imuseEffecct
Hook aufgerufen. Wir verwenden dieif
-Anweisung, um zu überprüfen, obisLoading
true
ist. Wenn diestrue
ist, ist der Bildschirm, den wir zurückgeben, unser<TransitionScreen />
, den wir zuvor erstellt haben, da die FunktioncheckAuthenticationStatus()
noch nicht vollständig ist. - Sobald unser
checkAuthenticationStatus()
abgeschlossen ist, wirdisLoading
auffalse
gesetzt und wir geben unsere Hauptnavigationskomponenten zurück. - Der
NavigationContainer
wurde aus@react-navigation/native
importiert. Es wird nur einmal im Hauptnavigator der obersten Ebene verwendet. Beachten Sie, dass wir dies nicht in preAuthNavigator.js oder postAuthNavigator.js verwenden. - In unserem
AppNavigator()
erstellen wir noch einen Stack-Navigator. Wenn das von unserer Context-API erhalteneuserToken
null
ist, mounten wir denPreAuthNavigator
, wenn sein Wert etwas anderes ist (was bedeutet, dassAsyncStorage.getItem()
incheckAuthenticationStatus()
einen tatsächlichen Wert zurückgegeben hat), dann mounten wir denPostAuthNavigator
. Unser bedingtes Rendering erfolgt mit dem ternären Operator.
Jetzt haben wir unsere AppNavigator.js eingerichtet. Als nächstes müssen wir unseren AppNavigator
an unsere App.js- Datei übergeben.
Übergeben wir unseren AppNavigator
an die App.js -Datei:
App.js
... import AppNavigator from './views/navigation/AppNavigator'; ... return ( <AuthState> <AppNavigator /> </AuthState> );
Sehen wir uns nun an, wie unsere App im Moment aussieht:
Folgendes passiert, wenn Sie beim Versuch, sich anzumelden, falsche Anmeldedaten angeben:
Hinzufügen der Abmeldefunktion
An diesem Punkt ist unser Authentifizierungs- und Routenauswahlprozess abgeschlossen. Das einzige, was für unsere App übrig bleibt, ist das Hinzufügen der Abmeldefunktion.
Die Abmeldeschaltfläche befindet sich in der Datei HomeScreen.js . Wir haben eine onLogout()
Funktion an das onPress
Attribut der Schaltfläche übergeben. Im Moment haben wir eine einfache console.log()
in unserer Funktion, aber das wird sich in Kürze ändern.
Gehen wir nun zu unserer AuthState.js und schreiben die Funktion zum Abmelden. Diese Funktion löscht einfach den AsyncStorage
in dem das Benutzertoken gespeichert ist.
Kontext > authContext > AuthState.js
... const AuthState = (props) => { ... const userSignout = async() => { await AsyncStorage.removeItem('user-token'); setUserToken(null); } return ( ... ) } export default AuthState;
Das userSignout()
ist eine asynchrone Funktion, die das user-token
aus unserem AsyncStorage
.
Jetzt müssen wir jedes Mal, wenn auf die Abmeldeschaltfläche geklickt wird, die Funktion userSignout()
in unserer HomeScreen.js aufrufen .
Gehen wir zu unserer HomeScreen.js und verwenden Sie die userSignout()
von unserem AuthContext
.
screens > 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> ) } ...
Im obigen Codeblock haben wir den useContext
Hook aus ReactJS importiert, dann haben wir unseren AuthContext importiert. Als nächstes haben wir die userSignout
Funktion aus unserem AuthContext
und diese userSignout()
Funktion wird in unserer onLogout()
-Funktion aufgerufen.
Wenn jetzt auf unsere Abmeldeschaltfläche geklickt wird, wird das Benutzertoken in unserem AsyncStorage
gelöscht.
Voila! Unser gesamter Prozess ist abgeschlossen.
Folgendes passiert, wenn Sie nach der Anmeldung auf die Schaltfläche „Zurück“ klicken:
Folgendes passiert, wenn Sie nach dem Abmelden die Zurück-Taste drücken:
Hier sind einige unterschiedliche Verhaltensweisen, die wir bemerken, wenn wir dieses Muster in unserem Navigationsstapelwechsel verwenden:
- Sie werden feststellen, dass wir nirgendwo
navigation.navigate()
odernavigation.push()
verwenden mussten, um nach der Anmeldung zu einer anderen Route zu gehen. Sobald unser Status mit dem Benutzertoken aktualisiert wurde, wird der gerenderte Navigationsstapel automatisch geändert. - Das Drücken der Zurück-Taste auf Ihrem Gerät nach erfolgreicher Anmeldung bringt Sie nicht zurück zur Anmeldeseite, sondern schließt die App vollständig. Dieses Verhalten ist wichtig, da Sie nicht möchten, dass der Benutzer zur Anmeldeseite zurückkehren kann, es sei denn, er meldet sich von der App ab. Das Gleiche gilt für das Abmelden – sobald sich der Benutzer abgemeldet hat, kann er nicht mit der Zurück-Taste zum
HomeScreen
-Bildschirm zurückkehren, sondern die App wird geschlossen.
Fazit
In vielen Apps ist die Authentifizierung einer der wichtigsten Teile, da sie bestätigt, dass die Person, die versucht, Zugang zu geschützten Inhalten zu erhalten, das Recht hat, auf die Informationen zuzugreifen. Zu lernen, wie man es richtig macht, ist ein wichtiger Schritt beim Erstellen einer großartigen, intuitiven und einfach zu bedienenden/navigierbaren Anwendung.
Aufbauend auf diesem Code sind hier einige Dinge, die Sie hinzufügen könnten:
- Formularvalidierung zur Validierung von Eingabefeldern. Sehen Sie sich die React Native-Formularvalidierung mit Formik und Yup an.
- Firebase-Authentifizierung zur Integration der Authentifizierung mit Gmail, Github, Facebook, Twitter oder Ihrer benutzerdefinierten Oberfläche. Sehen Sie sich React Native Firebase an.
- Codekonzepte für Designer: Authentifizierung und Autorisierung.
Hier sind auch einige wichtige Ressourcen, die ich gefunden habe, die Sie mehr über Authentifizierung, Sicherheit und wie man es richtig macht, aufklären werden:
Ressourcen
- Reagieren Sie nativ: Ablauf der Benutzerauthentifizierung erklärt
- 10 Best Practices für React-Sicherheit
- Authentifizierungsmethoden, die den nächsten Verstoß verhindern können
- Sehen Sie sich hier einen Live-Build/eine Vorschau unserer Anwendung an;
- Sehen Sie sich das Projekt auf GitHub an.