Manipularea montajului și demontării rutelor de navigație în React Native

Publicat: 2022-03-10
Rezumat rapid ↬ Adesea aveți nevoie de două seturi diferite de stive de navigare pentru autentificarea pre și post utilizator. De obicei, pentru a vedea mai mult conținut, trebuie să fii autentificat într-un fel. Să ne uităm la cum să montați și să demontați stiva de navigare pe baza unei condiții îndeplinite în React Native.

În acest articol, vom parcurge montarea și demontarea rutelor de navigație în React Native. Un comportament așteptat al aplicației dvs. este că, odată ce condiția de autentificare este îndeplinită, un nou set de rute de navigare este disponibil numai pentru utilizatorii conectați, în timp ce celelalte ecrane care au fost afișate înainte de autentificare sunt eliminate și nu pot fi returnate decât dacă utilizatorul se deconectează de la aplicație.

Pentru securitatea aplicației dvs., rutele protejate vă oferă o modalitate de a afișa numai anumite informații/conținut din aplicație anumitor utilizatori, restricționând în același timp accesul persoanelor neautorizate.

Vom lucra cu Expo pentru acest proiect, deoarece ne va ajuta să ne concentrăm asupra problemei în cauză în loc să ne facem griji pentru o mulțime de setări. Aceiași pași din acest articol ar putea fi urmați pentru o aplicație React Native.

Aveți nevoie de puțină familiaritate cu JavaScript și React Native pentru a continua acest tutorial. Iată câteva lucruri importante cu care ar trebui să fii deja familiarizat:

  • Componente personalizate în React Native (cum să creați componente, să primiți, să transmiteți și să utilizați elemente de recuzită într-o componentă). Citeste mai mult.
  • React Navigation. Citeste mai mult.
  • Stack Navigator în React Native. Citeste mai mult.
  • Cunoștințe de bază despre componentele React Native Core ( <View/> , <Text/> , etc.). Citeste mai mult.
  • React Native AsyncStorage . Citeste mai mult.
  • Context API. Citeste mai mult.

Configurarea proiectului și autentificarea de bază

Dacă sunteți nou în utilizarea expo și nu știți cum să instalați expo, vizitați documentația oficială. Odată ce instalarea este finalizată, continuați să inițializați un nou proiect React Native cu expo din promptul nostru de comandă:

 expo init navigation-project

Vi se vor prezenta câteva opțiuni pentru a alege cum doriți să fie configurația de bază:

Reactează configurația de bază a proiectului Native
(Previzualizare mare)

În cazul nostru, să selectăm prima opțiune pentru a configura proiectul nostru ca document gol. Acum, așteptați până când instalarea dependențelor JavaScript este completă.

Odată ce aplicația noastră este configurată, ne putem schimba directorul în noul director de proiect și îl putem deschide în editorul de cod preferat. Trebuie să instalăm biblioteca pe care o vom folosi pentru AsyncStorage și bibliotecile noastre de navigare. În directorul folderului din terminalul dvs., lipiți comanda de mai sus și alegeți un șablon (un blank ar funcționa) pentru a instala dependențele de proiect.

Să ne uităm la ce este fiecare dintre aceste dependențe:

  • @react-native-community/async-storage
    La fel ca localStorage pe web, este un API React Native pentru păstrarea datelor pe un dispozitiv în perechi cheie-valoare.
  • @react-native-community/masked-view, react-native-screens, react-native-gesture-handle
    Aceste dependențe sunt utilități de bază care sunt utilizate de majoritatea navigatorilor pentru a crea structura de navigare în aplicație. (Citiți mai multe în Noțiuni introductive cu navigarea React Native.)
  • @react-navigation/native
    Aceasta este dependența pentru navigarea React Native.
  • @react-navigation/stiva
    Aceasta este dependența pentru navigarea stivei în 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

Pentru a porni aplicația, utilizați expo start din directorul aplicației din terminalul dvs. Odată ce aplicația este pornită, puteți utiliza aplicația expo de pe telefonul mobil pentru a scana codul de bare și a vizualiza aplicația, sau dacă aveți un emulator Android/simulator IOS, puteți deschide aplicația prin intermediul acestora din instrumentul de dezvoltare expo care se deschide în browser când porniți o aplicație expo. Pentru exemplele de imagini din acest articol, vom folosi Genymotions pentru a vedea rezultatul nostru. Iată cum va arăta rezultatul nostru final în Genymotions:

rezultatul final în Genymotions
(Previzualizare mare)

Structuri de foldere

Să ne creăm structura de foldere de la început, astfel încât să ne fie mai ușor să lucrăm cu ea pe măsură ce procedăm:

Avem nevoie de două foldere mai întâi:

  • context
    Acest folder va păstra contextul pentru întreaga noastră aplicație, deoarece vom lucra cu Context API pentru gestionarea globală a stării.
  • vederi
    Acest folder va deține atât folderul de navigare, cât și vizualizările pentru diferite ecrane.

Continuați și creați cele două foldere în directorul proiectului.

În folderul context, creați un folder numit authContext și creați două fișiere în interiorul folderului authContext :

  • AuthContext.js ,
  • AuthState.js .

Vom avea nevoie de aceste fișiere când vom începe să lucrăm cu Context API.

Acum mergeți la folderul de vizualizări pe care l-am creat și creați încă două foldere în interiorul acestuia, și anume:

  • navigatie ,
  • ecrane .

Acum, nu am terminat încă, în folderul ecrane , creați încă două foldere:

  • postAuthScreens ,
  • preAuthScreens .

Dacă ați urmat corect configurarea folderului, așa ar trebui să arate structura dvs. de folder în acest moment:

structura folderului
(Previzualizare mare)
Mai multe după săritură! Continuați să citiți mai jos ↓

Crearea primului nostru ecran

Acum să creăm primul nostru ecran și să-l numim welcomeScreen.js în folderul preAuthScreens .

preAuthScreens > welcomeScreen.js

Iată conținutul fișierului nostru 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

Iată ce am făcut în blocul de cod de mai sus:

Mai întâi, am importat lucrurile de care avem nevoie din biblioteca React Native, și anume, View , Text , Button , TextInput . Apoi, am creat componenta noastră funcțională WelcomeScreen .

Veți observa că am importat StyleSheet din React Native și am folosit-o pentru a defini stiluri pentru antetul nostru și, de asemenea, pentru <TextInput /> .

În cele din urmă, exportăm componenta WelcomeScreen din partea de jos a codului.

Acum că am terminat cu asta, să facem ca această componentă să funcționeze așa cum era de așteptat, folosind cârligul useState pentru a stoca valorile intrărilor și a le actualiza stările ori de câte ori are loc o modificare în câmpurile de intrare. Vom aduce și importul useCallback hook de la React, deoarece vom avea nevoie de el mai târziu pentru a menține o funcție.

În primul rând, în timp ce suntem încă în componenta WelcomeScreen , trebuie să importam useState și useCallback din React.

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

Acum, în interiorul componentei funcționale WelcomeScreen , să creăm cele două stări pentru e-mail și respectiv parolă:

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

În continuare, trebuie să ne modificăm câmpurile <TextInput /> astfel încât să-și obțină valoarea din stările respective și să-și actualizeze starea atunci când valoarea intrării este actualizată:

 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> ) } ...

În codul de mai sus, iată ce am făcut:

  • Am făcut ca value fiecărei intrări de text să indice stările lor respective.
  • Am adăugat handlerul onChangeText la intrările noastre de text. Aceasta se declanșează de fiecare dată când o nouă valoare este introdusă sau ștearsă din câmpurile de intrare.
  • Am numit funcția noastră onInputChange care acceptă două argumente:
    • value curentă este furnizată de handler-ul onChangeText .
    • Setter-ul stării care ar trebui actualizat (pentru primul câmp de intrare trecem setEmail și al doilea trecem setPassword .
    • În cele din urmă, scriem funcția noastră onInputChange , iar funcția noastră face un singur lucru: actualizează stările respective cu noua valoare.

Următorul lucru la care trebuie să lucrăm este funcția onUserAuthentication() cu care este apelată de fiecare dată când se face clic pe butonul pentru trimiterea formularului.

În mod ideal, utilizatorul trebuie să-și fi creat deja un cont, iar autentificarea va implica o logică de tip backend pentru a verifica dacă utilizatorul există și apoi a atribui un token utilizatorului. În cazul nostru, deoarece nu folosim niciun backend, vom crea un obiect care conține detaliile corecte de conectare a utilizatorului și apoi vom autentifica un utilizator numai atunci când valorile pe care le introduce se potrivesc cu valorile noastre fixe din obiectul de conectare al e- email și al password pe care le vom autentifica. crea.

Iată codul de care avem nevoie pentru a face asta:

 ... 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 ( ... ) } ...

Unul dintre primele lucruri pe care le veți observa în codul de mai sus este că am definit un correctAuthenticationDetails (care este un obiect care deține detaliile de conectare corecte pe care ne așteptăm să le furnizeze utilizatorul) în afara componentei funcționale WelcomeScreen() .

Apoi, am scris conținutul funcției onUserAuthentication() și am folosit o declarație condiționată pentru a verifica dacă e- email sau password deținute în statele respective nu se potrivește cu cea pe care am furnizat-o în obiectul nostru.

Dacă doriți să vedeți ce am făcut până acum, importați componenta WelcomeScreen în App.js astfel:

Deschideți fișierul App.js și puneți acesta înlocuiți întregul cod cu acesta:

 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> ); }

Privind îndeaproape codul de mai sus, veți vedea că ceea ce am făcut a fost să importam componenta WelcomeScreen și apoi să o folosim în funcția App() .

Iată cum arată rezultatul WelcomeScreen nostru de bun venit:

rezultatul WelcomeScreen
(Previzualizare mare)

Acum că am terminat de construit componenta WelcomeScreen , să mergem mai departe și să începem să lucrăm cu Context API pentru a gestiona starea noastră globală.

De ce Context API?

Folosind Context API, nu este nevoie să instalăm nicio bibliotecă suplimentară în ReactJS, este mai puțin stresant de configurat și este una dintre cele mai populare moduri de a gestiona starea globală în ReactJS. Pentru gestionarea ușoară a stării, este o alegere bună.

Crearea contextului nostru

Dacă vă amintiți, am creat mai devreme un folder de context și am creat un subdosar în interiorul acestuia numit authContext .

Acum să navigăm la fișierul AuthContext.js din folderul authContext și să creăm contextul nostru:

context > authContext > AuthContext.js

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

AuthContext pe care tocmai l-am creat deține valoarea stării de loading și valorile stării userToken . În prezent, în createContext pe care l-am declarat în blocul de cod de mai sus, nu am inițializat nicio valoare implicită aici, așa că contextul nostru este momentan undefined . Un exemplu de valoare a contextului de autentificare ar putea fi {loading: false, userToken: 'abcd}

Fișierul AuthState.js deține logica noastră Context API și valorile de stare ale acestora. Funcțiile scrise aici pot fi apelate de oriunde în aplicația noastră și atunci când actualizează valorile în stare, este actualizată și la nivel global.

Mai întâi, să aducem toate importurile de care vom avea nevoie în acest fișier:

context > AuthContext > AuthState.js

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

Am importat cârligul useState() din ReactJS pentru a ne păstra stările, am importat fișierul AuthContext pe care l-am creat mai sus, deoarece aici este inițializat contextul nostru gol pentru autentificare și va trebui să-l folosim așa cum veți vedea mai târziu în timp ce progresăm. , în cele din urmă importăm pachetul AsyncStorage (similar cu localStorage pentru web).

AsyncStorage este un API React Native care vă permite să păstrați datele offline pe dispozitiv într-o aplicație 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;

În blocul de cod de mai sus, iată ce am făcut:

  • Am declarat două stări pentru userToken și isLoading . Starea userToken va fi folosită pentru a stoca simbolul salvat în AsyncStorage , în timp ce starea isLoading va fi folosită pentru a urmări starea de încărcare (inițial este setată la true ). Vom afla mai multe despre utilizarea acestor două stări pe măsură ce procedăm.

  • Apoi, am scris funcția noastră onAuthentication() . Această funcție este o funcție async care este apelată atunci când se face clic pe butonul de conectare din fișierul welcomeScreen.jsx . Această funcție va fi apelată numai dacă e-mailul și parola pe care utilizatorul le-a furnizat se potrivesc cu obiectul corect pentru detaliile utilizatorului pe care l-am furnizat. De obicei, ceea ce se întâmplă în timpul autentificării este că un token este generat pentru utilizator după ce utilizatorul este autentificat pe backend folosind un pachet precum JWT, iar acest token este trimis către front-end. Deoarece nu vom aborda toate acestea pentru acest tutorial, am creat un token static și l-am păstrat într-o variabilă numită USER_TOKEN .

  • Apoi, folosim cuvântul cheie await pentru a seta simbolul de utilizator la AsyncStorage cu numele user-token . Declarația console.warn() este folosită doar pentru a verifica dacă totul a mers bine, o puteți scoate oricând doriți.

  • În cele din urmă, transmitem funcția noastră onAuthenticated ca valoare în interiorul <AuthContext.Provider> , astfel încât să putem accesa și apela funcția de oriunde în aplicația noastră.

ecrane > preAuth > welcomeScreen.js

Mai întâi, importați useContext din ReactJS și importați AuthContext din fișierul AuthContext.js .

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

Acum, în interiorul componentei funcționale welcomeScreen() , să folosim contextul pe care l-am creat:

 ... 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 ( ... ) } ...

În blocul de cod de mai sus, am destructurat funcția onAuthentication din AuthContext și apoi am numit-o în cadrul funcției noastre onUserAuthentication() și am eliminat instrucțiunea console.log() care era acolo până acum.

În acest moment, aceasta va genera o eroare, deoarece nu avem încă acces la AuthContext . Pentru a utiliza AuthContext oriunde în aplicația dvs., trebuie să împachetăm fișierul de nivel superior din aplicația noastră cu AuthState (în cazul nostru, este fișierul App.js ).

Accesați fișierul App.js și înlocuiți codul de acolo cu acesta:

 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> ); }

Am ajuns atât de departe și am terminat cu această secțiune. Înainte de a trece la următoarea secțiune în care ne-am configurat rutarea, să creăm un nou ecran. Ecranul pe care urmează să îl creăm va fi fișierul HomeScreen.js care ar trebui să apară numai după autentificarea cu succes.

Accesați: ecrane > postAuth .

Creați un fișier nou numit HomeScreen.js . Iată codul pentru fișierul HomeScreen.js :

ecrane > 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

Deocamdată, butonul de deconectare are o instrucțiune falsă console.log() . Mai târziu, vom crea funcționalitatea de deconectare și o vom trece pe ecran din contextul nostru.

Configurarea rutelor noastre

Trebuie să creăm trei (3) fișiere în folderul nostru de navigare:

  • postAuthNavigator.js ,
  • preAuthNavigator.js ,
  • AppNavigator.js .

După ce ați creat aceste trei fișiere, navigați la fișierul preAuthNaviagtor.js pe care tocmai l-ați creat și scrieți asta:

navigare > 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;

În fișierul de mai sus, iată ce am făcut:

  • Am importat createStackNavigator din @react-navigation/stack pe care îl folosim pentru navigarea în stivă. createStackNavigator Oferă o modalitate prin care aplicația dvs. să facă tranziția între ecrane în care fiecare ecran nou este plasat deasupra unei stive. În mod implicit, navigatorul de stivă este configurat pentru a avea aspectul și senzația familiar iOS și Android: ecranele noi glisează din dreapta pe iOS, se estompează de jos pe Android. Faceți clic aici dacă doriți să aflați mai multe despre navigatorul de stivă din React Native.
  • Am destructurat Navigator și Screen din createStackNavigator() .
  • În declarația de returnare, ne-am creat navigarea cu <Navigator/> și ne-am creat ecranul cu <Screen/> . aceasta înseamnă că dacă am avut mai multe ecrane care pot fi accesate înainte de autentificare, vom avea mai multe etichete <Screen/> aici reprezentându-le.
  • În cele din urmă, exportăm componenta noastră PreAuthNavigator .

Să facem un lucru similar pentru fișierul postAuthNavigator.js .

navigare > 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;

După cum vedem în codul de mai sus, singura diferență între preAuthNavigator.js și postAuthNavigator.js este afișarea ecranului. În timp ce primul primește ecranul de bun venit, WelcomeScreen preia ecranul HomeScreen pornire .

Pentru a crea AppNavigator.js , trebuie să creăm câteva lucruri.

Deoarece AppNavigator.js este locul în care vom comuta și vom verifica ce rută va fi disponibilă pentru acces de către utilizator, avem nevoie de mai multe ecrane pentru ca acest lucru să funcționeze corect, să subliniem lucrurile pe care trebuie să le creăm mai întâi:

  1. TransitionScreen.js
    În timp ce aplicația decide ce navigație va monta, dorim să apară un ecran de tranziție. De obicei, ecranul de tranziție va fi un rotisor de încărcare sau orice altă animație personalizată aleasă pentru aplicație, dar în cazul nostru, vom folosi o etichetă de bază <Text/> pentru a afișa loading… .
  2. checkAuthenticationStatus()
    Această funcție este ceea ce vom apela pentru a verifica starea de autentificare, care va determina ce stivă de navigare va fi montată. Vom crea această funcție în contextul nostru și o vom folosi în Appnavigator.js .

Acum, să mergem mai departe și să creăm fișierul nostru TransitionScreen.js .

ecrane > TransitionScreen.js

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

Ecranul nostru de tranziție este doar un ecran simplu care arată textul de încărcare. Vom vedea unde să folosim acest lucru pe măsură ce procedăm în acest articol.

Apoi, să mergem la AuthState.js și să scriem checkAuthenticationStatus() :

context > 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;

În blocul de cod de mai sus, am scris funcția checkAuthenticationStatus() . În funcția noastră, iată ce facem:

  • Am folosit cuvântul cheie await pentru a obține indicativul nostru de la AsyncStorage . Cu AsyncStorage , dacă nu este furnizat niciun simbol, acesta returnează null . De asemenea, starea noastră inițială userToken este setată la null .
  • Folosim setUserToken pentru a seta valoarea returnată de la AsyncStorage ca noul nostru userToken . Dacă valoarea returnată este null , înseamnă că userToken -ul nostru rămâne null .
  • După blocul try{}…catch(){} , setăm isLoading la false deoarece funcția de verificare a stării de autentificare este completă. Vom avea nevoie de valoarea isLoading pentru a ști dacă ar trebui să afișăm în continuare TransitionScreen sau nu. Merită să luați în considerare setarea unei erori dacă există o eroare la preluarea jetonului, astfel încât să putem arăta utilizatorului un buton „Reîncercați” sau „Încercați din nou” atunci când se întâlnește eroarea.
  • Ori de câte ori se montează AuthState , vrem să verificăm starea de autentificare, așa că folosim useEffect() ReactJS pentru a face acest lucru. Apelăm funcția noastră checkAuthenticationStatus() în interiorul cârligului useEffect() și setăm valoarea isLoading la false când se termină.
  • În cele din urmă, adăugăm stările noastre la valorile noastre <AuthContext.Provider/> , astfel încât să le putem accesa de oriunde în aplicația noastră acoperită de API-ul Context.

Acum că avem funcția noastră, este timpul să ne întoarcem la AppNavigator.js și să scriem codul pentru montarea unui anumit navigator de stivă pe baza stării de autentificare:

navigare > AppNavigator.js

În primul rând, vom importa tot ce avem nevoie pentru 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";

Acum că avem toate importurile noastre, să creăm funcția AppNavigator() .

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

În continuare, vom continua să scriem conținutul funcției noastre 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

În blocul de cod de mai sus, iată o schiță a ceea ce am făcut:

  • Am creat un navigator de stivă și am destructurat Navigator și Screen din acesta.
  • Am importat userToken -ul și isLoading din AuthContext
  • Când se montează AuthState , checkAuthenticationStatus() este apelat în hook-ul useEffecct de acolo. Folosim instrucțiunea if pentru a verifica dacă isLoading este true , dacă este true , ecranul pe care îl returnăm este <TransitionScreen /> pe care l-am creat mai devreme deoarece funcția checkAuthenticationStatus() nu este încă completă.
  • Odată ce checkAuthenticationStatus() este complet, isLoading este setat la false și returnăm componentele noastre principale de navigare.
  • NavigationContainer a fost importat din @react-navigation/native . Este folosit o singură dată în navigatorul principal de nivel superior. Observați că nu folosim acest lucru în preAuthNavigator.js sau în postAuthNavigator.js.
  • În AppNavigator() , creăm în continuare un navigator de stivă. Dacă userToken -ul obținut din API-ul nostru Context este null , PreAuthNavigator , dacă valoarea lui este altceva (înseamnă că AsyncStorage.getItem() din checkAuthenticationStatus() a returnat o valoare reală), atunci montem PostAuthNavigator . Redarea noastră condiționată se face folosind operatorul ternar.

Acum am configurat AppNavigator.js . Apoi, trebuie să trecem AppNavigator în fișierul nostru App.js.

Să trecem AppNavigator în fișierul App.js :

App.js

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

Să vedem acum cum arată aplicația noastră în acest moment:

Iată ce se întâmplă când furnizați o autentificare incorectă în timp ce încercați să vă conectați:

Adăugarea funcției de deconectare

În acest moment, procesul nostru de autentificare și selecție a rutei este finalizat. Singurul lucru rămas pentru aplicația noastră este să adăugați funcționalitatea de deconectare.

Butonul de deconectare se află în fișierul HomeScreen.js . Am transmis o onLogout() atributului onPress al butonului. Pentru moment, avem o instrucțiune simplă console.log() în funcția noastră, dar în puțin timp asta se va schimba.

Acum, să mergem la AuthState.js și să scriem funcția pentru deconectare. Această funcție pur și simplu șterge AsyncStorage unde este salvat simbolul utilizatorului.

context > authContext > AuthState.js

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

userSignout() este o funcție asincronă care elimină user-token din AsyncStorage .

Acum trebuie să apelăm funcția userSignout() din HomeScreen.js de fiecare dată când se face clic pe butonul de deconectare.

Să mergem la HomeScreen.js și să folosim userSignout userSignout() din AuthContext .

ecrane > 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> ) } ...

În blocul de cod de mai sus, am importat cârligul useContext din ReactJS, apoi am importat AuthContext. Apoi, am destructurat funcția userSignout din AuthContext și această userSignout() este apelată în funcția noastră onLogout() .

Acum, de fiecare dată când se face clic pe butonul nostru de deconectare, simbolul utilizatorului din AsyncStorage este șters.

Voila! întregul nostru proces este încheiat.

Iată ce se întâmplă când apăsați butonul Înapoi după ce v-ați conectat:

Apăsând butonul Înapoi după conectarea la aplicație.

Iată ce se întâmplă când apăsați butonul Înapoi după deconectare:

Apăsând butonul Înapoi după deconectarea din aplicație.

Iată câteva comportamente diferite pe care le observăm când folosim acest model în comutarea stivei de navigare:

  1. Veți observa că nu era nici un loc de care trebuia să folosim navigation.navigate() sau navigation.push() pentru a merge la o altă rută după autentificare. Odată ce starea noastră este actualizată cu simbolul utilizatorului, stiva de navigare redată este schimbată automat.
  2. Apăsarea butonului Înapoi de pe dispozitiv după ce autentificarea a reușit nu vă poate duce înapoi la pagina de conectare, în schimb, aceasta închide aplicația complet. Acest comportament este important deoarece nu doriți ca utilizatorul să se poată întoarce înapoi la pagina de conectare, cu excepția cazului în care se deconectează din aplicație. Același lucru este valabil și pentru deconectare - odată ce utilizatorul se deconectează, nu poate folosi butonul înapoi pentru a reveni la ecranul HomeScreen , dar, în schimb, aplicația se închide.

Concluzie

În multe aplicații, autentificarea este una dintre cele mai importante părți, deoarece confirmă că persoana care încearcă să obțină acces la conținut protejat are dreptul de a accesa informațiile. A învăța cum să o faci corect este un pas important în construirea unei aplicații grozave, intuitive și ușor de utilizat/navigat.

Pe baza acestui cod, iată câteva lucruri pe care ați putea să le adăugați:

  • Validare formular pentru validarea câmpurilor de intrare. Verificați validarea formularului React Native cu Formik și Yup.
  • Autentificare Firebase pentru integrarea autentificării cu Gmail, Github, Facebook, Twitter sau cu interfața dvs. personalizată. Consultați React Native Firebase.
  • Concepte de cod pentru designeri: Autentificare și Autorizare.

Iată, de asemenea, câteva resurse importante pe care le-am găsit, care vă vor lumina mai mult despre autentificare, securitate și cum să o faceți corect:

Resurse

  • React Native: Fluxul de autentificare a utilizatorului explicat
  • 10 cele mai bune practici de securitate React
  • Metode de autentificare care pot preveni următoarea încălcare
  • Vizualizați o versiune live/previzualizare a aplicației noastre aici;
  • Vizualizați proiectul pe GitHub.