การจัดการการติดตั้งและการยกเลิกการต่อเชื่อมเส้นทางการนำทางใน React Native

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ บ่อยครั้งที่คุณต้องการชุดการนำทางที่แตกต่างกันสองชุดสำหรับการตรวจสอบสิทธิ์ผู้ใช้ก่อนและหลัง โดยปกติ หากต้องการดูเนื้อหาเพิ่มเติม คุณต้องตรวจสอบสิทธิ์ด้วยวิธีใดวิธีหนึ่ง มาดูวิธีการเมาต์และเลิกเมานท์การนำทางสแต็กตามเงื่อนไขที่ตรงตามใน React Native

ในบทความนี้ เราจะพูดถึงการ ติดตั้งและยกเลิกการต่อเชื่อมเส้นทางการนำทาง ใน React Native ลักษณะการทำงานที่คาดหวังของแอปของคุณคือเมื่อตรงตามเงื่อนไขการตรวจสอบสิทธิ์แล้ว เส้นทางการนำทางชุดใหม่จะพร้อมใช้งานสำหรับผู้ใช้ที่ลงชื่อเข้าใช้เท่านั้น ในขณะที่หน้าจออื่นๆ ที่แสดงก่อนการตรวจสอบสิทธิ์จะถูกลบออกและไม่สามารถย้อนกลับได้เว้นแต่ ผู้ใช้ออกจากระบบแอปพลิเคชัน

เพื่อความปลอดภัยในแอปของคุณ เส้นทางที่มีการป้องกันจะให้คุณแสดงเฉพาะข้อมูล/เนื้อหาบางอย่างในแอปของคุณต่อผู้ใช้บางราย ในขณะที่จำกัดการเข้าถึงจากบุคคลที่ไม่ได้รับอนุญาต

เราจะทำงานร่วมกับ Expo สำหรับโปรเจ็กต์นี้ เพราะมันจะช่วยให้เราโฟกัสที่ปัญหาในมือ แทนที่จะต้องกังวลกับการตั้งค่าจำนวนมาก คุณสามารถทำตามขั้นตอนเดียวกันในบทความนี้สำหรับแอปพลิเคชัน React Native เปล่า

คุณต้องมีความคุ้นเคยกับ JavaScript และ React Native เพื่อทำตามบทช่วยสอนนี้ ต่อไปนี้คือสิ่งสำคัญบางประการที่คุณน่าจะคุ้นเคยอยู่แล้ว:

  • ส่วนประกอบที่กำหนดเองใน React Native (วิธีสร้างส่วนประกอบ รับ ส่งผ่าน และใช้อุปกรณ์ประกอบฉากในส่วนประกอบ) อ่านเพิ่มเติม.
  • ตอบสนองการนำทาง อ่านเพิ่มเติม.
  • Stack Navigator ใน React Native อ่านเพิ่มเติม.
  • ความรู้พื้นฐานเกี่ยวกับส่วนประกอบ React Native Core ( <View/> , <Text/> ฯลฯ) อ่านเพิ่มเติม.
  • ตอบสนอง Native AsyncStorage อ่านเพิ่มเติม.
  • บริบท API อ่านเพิ่มเติม.

การตั้งค่าโปรเจ็กต์และการตรวจสอบฐาน

หากคุณเพิ่งเริ่มใช้งานงานมหกรรมและไม่ทราบวิธีการติดตั้งงานเอ็กซ์โป โปรดไปที่เอกสารประกอบอย่างเป็นทางการ เมื่อการติดตั้งเสร็จสิ้น ให้เริ่มต้นโครงการ React Native ใหม่ด้วย expo จากพรอมต์คำสั่งของเรา:

 expo init navigation-project

คุณจะเห็นตัวเลือกบางอย่างเพื่อเลือกวิธีที่คุณต้องการให้การตั้งค่าพื้นฐานเป็น:

ตอบสนองการตั้งค่าพื้นฐานของโปรเจ็กต์เนทีฟ
(ตัวอย่างขนาดใหญ่)

ในกรณีของเรา ให้เลือกตัวเลือกแรกเพื่อตั้งค่าโครงการของเราเป็นเอกสารเปล่า ตอนนี้ ให้รอจนกว่าการติดตั้งการพึ่งพา JavaScript จะเสร็จสมบูรณ์

เมื่อแอปของเราได้รับการตั้งค่าแล้ว เราสามารถเปลี่ยนไดเร็กทอรีของเราเป็นไดเร็กทอรีโครงการใหม่และเปิดในโปรแกรมแก้ไขโค้ดที่คุณชื่นชอบ เราจำเป็นต้องติดตั้งไลบรารีที่เราจะใช้สำหรับ AsyncStorage และไลบรารีการนำทางของเรา ภายในไดเร็กทอรีโฟลเดอร์ของคุณในเทอร์มินัล ให้วางคำสั่งด้านบนและเลือกเทมเพลต ( blank ก็ใช้ได้) เพื่อติดตั้งการพึ่งพาโปรเจ็กต์ของเรา

มาดูกันว่าแต่ละการพึ่งพาเหล่านี้มีไว้เพื่ออะไร:

  • @react-native-community/async-storage
    เช่นเดียวกับ localStorage บนเว็บ มันคือ React Native API สำหรับเก็บข้อมูลบนอุปกรณ์ในคู่คีย์-ค่า
  • @react-native-community/masked-view, react-native-screens, react-native-gesture-handle
    การพึ่งพาเหล่านี้เป็นยูทิลิตี้หลักที่เนวิเกเตอร์ส่วนใหญ่ใช้เพื่อสร้างโครงสร้างการนำทางในแอป (อ่านเพิ่มเติมใน การเริ่มต้นใช้งาน React Native navigation)
  • @react-navigation/native
    นี่คือการพึ่งพาการนำทาง React Native
  • @react-navigation/stack
    นี่คือการพึ่งพาการนำทางสแต็กใน 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

ในการเริ่มแอปพลิเคชัน ให้ใช้ expo start จากไดเร็กทอรีของแอพในเทอร์มินัลของคุณ เมื่อเริ่มต้นแอปแล้ว คุณสามารถใช้แอปงานเอ็กซ์โปจากโทรศัพท์มือถือของคุณเพื่อสแกนบาร์โค้ดและดูแอปพลิเคชัน หรือหากคุณมีเครื่องจำลอง Android/เครื่องจำลอง IOS คุณสามารถเปิดแอปผ่านแอปเหล่านี้ได้จากเครื่องมือสำหรับนักพัฒนางานเอ็กซ์โป เปิดขึ้นในเบราว์เซอร์ของคุณเมื่อคุณเริ่มแอปพลิเคชันงานแสดงสินค้า สำหรับตัวอย่างรูปภาพในบทความนี้ เราจะใช้ Genymotions เพื่อดูผลลัพธ์ของเรา ผลลัพธ์สุดท้ายของเราจะเป็นอย่างไรใน Genymotions:

ผลลัพธ์สุดท้ายใน Genymotions
(ตัวอย่างขนาดใหญ่)

โครงสร้างโฟลเดอร์

ให้เราสร้างโครงสร้างโฟลเดอร์ของเราตั้งแต่เริ่มต้น เพื่อให้เราทำงานกับมันได้ง่ายขึ้นในขณะที่ดำเนินการต่อไป:

เราต้องการสองโฟลเดอร์ก่อน:

  • บริบท
    โฟลเดอร์นี้จะเก็บบริบทสำหรับแอปพลิเคชันทั้งหมดของเรา เนื่องจากเราจะทำงานร่วมกับ Context API สำหรับการจัดการสถานะทั่วโลก
  • มุมมอง
    โฟลเดอร์นี้จะเก็บทั้งโฟลเดอร์การนำทางและมุมมองสำหรับหน้าจอต่างๆ

ไปข้างหน้าและสร้างสองโฟลเดอร์ในไดเรกทอรีโครงการของคุณ

ภายในโฟลเดอร์บริบท ให้สร้างโฟลเดอร์ชื่อ authContext และสร้างสองไฟล์ภายในโฟลเดอร์ authContext :

  • AuthContext.js ,
  • AuthState.js

เราจะต้องใช้ไฟล์เหล่านี้เมื่อเราเริ่มทำงานกับ Context API

ไปที่โฟลเดอร์ มุมมอง ที่เราสร้างและสร้างอีกสองโฟลเดอร์ภายในนั้น ได้แก่:

  • การนำทาง ,
  • หน้าจอ

ตอนนี้ เรายังไม่เสร็จสิ้น ภายในโฟลเดอร์ หน้าจอ ให้สร้างอีกสองโฟลเดอร์นี้:

  • postAuthScreens ,
  • preAuthScreens

หากคุณปฏิบัติตามการตั้งค่าโฟลเดอร์อย่างถูกต้อง โครงสร้างโฟลเดอร์ของคุณควรมีลักษณะดังนี้:

โครงสร้างโฟลเดอร์
(ตัวอย่างขนาดใหญ่)
เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

การสร้างหน้าจอแรกของเรา

ตอนนี้ มาสร้างหน้าจอแรกของเราและเรียกมันว่า welcomeScreen.js ภายในโฟลเดอร์ preAuthScreens

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 ได้แก่ View , Text , Button , TextInput ต่อไป เราได้สร้างองค์ประกอบการทำงาน WelcomeScreen

คุณจะสังเกตเห็นว่าเรานำเข้า StyleSheet จาก React Native และใช้เพื่อกำหนดสไตล์สำหรับส่วนหัวของเราและ <TextInput /> ของเราด้วย

สุดท้าย เราส่งออกองค์ประกอบ WelcomeScreen ที่ด้านล่างของโค้ด

เมื่อเราทำสิ่งนี้เสร็จแล้ว ให้ส่วนประกอบนี้ทำงานตามที่คาดไว้โดยใช้ hook ของ useState เพื่อเก็บค่าของอินพุตและอัปเดตสถานะทุกครั้งที่มีการเปลี่ยนแปลงเกิดขึ้นในช่องใส่ นอกจากนี้เรายังจะนำเข้า useCallback hook จาก React เนื่องจากเราต้องการใช้ในภายหลังเพื่อคงฟังก์ชันไว้

อันดับแรก ในขณะที่เรายังอยู่ในองค์ประกอบ WelcomeScreen เราต้องนำเข้า useState และ useCallback จาก React

 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 ซึ่งยอมรับสองอาร์กิวเมนต์:
    • value ปัจจุบันมาจากตัวจัดการ onChangeText
    • ตัวกำหนดสถานะที่ควรได้รับการอัปเดต (สำหรับช่องป้อนข้อมูลแรกเราผ่าน setEmail และช่องที่สองที่เราส่ง setPassword
    • สุดท้าย เราเขียนฟังก์ชัน onInputChange ของเรา และฟังก์ชันของเราทำสิ่งเดียวเท่านั้น: อัปเดตสถานะที่เกี่ยวข้องด้วยค่าใหม่

สิ่งต่อไปที่เราต้องดำเนินการคือ onUserAuthentication() จะถูกเรียกเมื่อใดก็ตามที่มีการคลิกปุ่มสำหรับการส่งแบบฟอร์ม

ตามหลักการแล้ว ผู้ใช้จะต้องสร้างบัญชีแล้ว และการเข้าสู่ระบบจะเกี่ยวข้องกับตรรกะแบ็กเอนด์บางประเภท เพื่อตรวจสอบว่าผู้ใช้นั้นมีอยู่จริง จากนั้นจึงกำหนดโทเค็นให้กับผู้ใช้ ในกรณีของเรา เนื่องจากเราไม่ได้ใช้แบ็กเอนด์ เราจะสร้างออบเจ็กต์ที่มีรายละเอียดการเข้าสู่ระบบของผู้ใช้ที่ถูกต้อง จากนั้นจึงตรวจสอบสิทธิ์ผู้ใช้เมื่อค่าที่ป้อนตรงกับค่าคงที่ของเราจากออบเจ็กต์การเข้าสู่ระบบของ email และ password ที่เราจะ สร้าง.

นี่คือรหัสที่เราต้องทำ:

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

สิ่งแรกที่คุณจะสังเกตเห็นในโค้ดด้านบนคือเราได้กำหนด correctAuthenticationDetails (ซึ่งเป็นอ็อบเจ็กต์ที่มีรายละเอียดการเข้าสู่ระบบที่ถูกต้องซึ่งเราคาดหวังให้ผู้ใช้จัดหา) นอกองค์ประกอบการทำงาน WelcomeScreen()

ต่อไป เราเขียนเนื้อหาของ onUserAuthentication() และใช้คำสั่งแบบมีเงื่อนไขเพื่อตรวจสอบว่า email หรือ password ที่อยู่ในสถานะที่เกี่ยวข้องไม่ตรงกับที่เราให้ไว้ในวัตถุของเราหรือไม่

หากคุณต้องการดูว่าเราได้ทำอะไรไปแล้วบ้าง ให้นำเข้าองค์ประกอบ 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 เพื่อจัดการสถานะส่วนกลางของเรากัน

ทำไมต้อง Context API

เมื่อใช้ Context API เราไม่จำเป็นต้องติดตั้งไลบรารี่เพิ่มเติมใน ReactJS ทำให้การตั้งค่าไม่ยุ่งยาก และเป็นหนึ่งในวิธีที่นิยมที่สุดในการจัดการสถานะส่วนกลางใน ReactJS สำหรับการจัดการสถานะน้ำหนักเบาเป็นทางเลือกที่ดี

การสร้างบริบทของเรา

หากคุณจำได้ เราได้สร้างโฟลเดอร์ บริบท ไว้ก่อนหน้านี้ และสร้างโฟลเดอร์ย่อยภายในที่เรียกว่า authContext

ตอนนี้ ให้ไปที่ไฟล์ AuthContext.js ในโฟลเดอร์ authContext และสร้างบริบทของเรา:

บริบท > authContext > AuthContext.js

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

AuthContext ที่เราเพิ่งสร้างเก็บค่าสถานะการ loading และค่าสถานะ userToken ขณะนี้ ใน createContext ที่เราประกาศในบล็อคโค้ดด้านบน เราไม่ได้เริ่มต้นค่าเริ่มต้นใดๆ ที่นี่ ดังนั้นบริบทของเราจึง undefined ค่าตัวอย่างของบริบทการตรวจสอบสิทธิ์อาจเป็น {loading: false, userToken: 'abcd}

ไฟล์ AuthState.js เก็บตรรกะ Context API ของเราและค่าสถานะไว้ ฟังก์ชันที่เขียนที่นี่สามารถเรียกได้จากทุกที่ในแอปของเรา และเมื่ออัปเดตค่าในสถานะ ฟังก์ชันจะอัปเดตทั่วโลกด้วย

ขั้นแรก ให้นำเข้าทั้งหมดที่เราต้องการในไฟล์นี้:

บริบท > AuthContext > AuthState.js

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

เรานำเข้า useState() จาก ReactJS เพื่อเก็บสถานะของเรา เรานำเข้าไฟล์ AuthContext ที่เราสร้างขึ้นด้านบนเพราะนี่คือจุดเริ่มต้นของบริบทที่ว่างเปล่าสำหรับการตรวจสอบสิทธิ์ของเรา และเราจำเป็นต้องใช้มันดังที่คุณเห็นในภายหลังในขณะที่เราดำเนินการ ในที่สุด เราก็นำเข้าแพ็คเกจ AsyncStorage (คล้ายกับ 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;

ในบล็อกโค้ดด้านบนนี่คือสิ่งที่เราทำ:

  • เราประกาศสองสถานะสำหรับ userToken และ isLoading สถานะ userToken จะถูกใช้เพื่อจัดเก็บโทเค็นที่บันทึกไว้ใน AsyncStorage ในขณะที่สถานะ isLoading จะถูกใช้เพื่อติดตามสถานะการโหลด (ในขั้นต้นจะถูกตั้งค่า true ) เราจะหาข้อมูลเพิ่มเติมเกี่ยวกับการใช้สองสถานะนี้เมื่อเราดำเนินการต่อไป

  • ต่อไป เราเขียน onAuthentication() ฟังก์ชันนี้เป็นฟังก์ชัน async ที่เรียกใช้เมื่อมีการคลิกปุ่มเข้าสู่ระบบจากไฟล์ welcomeScreen.jsx ฟังก์ชันนี้จะถูกเรียกก็ต่อเมื่ออีเมลและรหัสผ่านที่ผู้ใช้ระบุตรงกับออบเจ็กต์รายละเอียดผู้ใช้ที่ถูกต้องที่เราให้ไว้ โดยปกติสิ่งที่เกิดขึ้นระหว่างการตรวจสอบความถูกต้องคือโทเค็นจะถูกสร้างขึ้นสำหรับผู้ใช้หลังจากที่ผู้ใช้ได้รับการตรวจสอบสิทธิ์ในแบ็กเอนด์โดยใช้แพ็คเกจเช่น JWT และโทเค็นนี้จะถูกส่งไปยังส่วนหน้า เนื่องจากเราไม่ได้กล่าวถึงทั้งหมดสำหรับบทช่วยสอนนี้ เราจึงสร้างโทเค็นแบบคงที่และเก็บไว้ในตัวแปรที่เรียกว่า USER_TOKEN

  • ต่อไป เราใช้คำสำคัญ await เพื่อตั้งค่าโทเค็นผู้ใช้ของเราเป็น AsyncStorage ด้วยชื่อ user-token คำสั่ง console.warn() ใช้เพื่อตรวจสอบว่าทุกอย่างถูกต้องแล้ว คุณสามารถถอดออกได้ทุกเมื่อที่ต้องการ

  • สุดท้าย เราส่งฟังก์ชัน onAuthenticated เป็นค่าภายใน <AuthContext.Provider> เพื่อให้เราสามารถเข้าถึงและเรียกใช้ฟังก์ชันได้จากทุกที่ในแอปของเรา

หน้าจอ > การตรวจสอบสิทธิ์ล่วงหน้า > welcomeScreen.js

ขั้นแรก นำเข้า useContext จาก ReactJS และนำเข้า AuthContext จากไฟล์ AuthContext.js

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

ในบล็อกโค้ดด้านบน เราได้ทำลายโครงสร้างฟังก์ชัน onAuthentication จาก AuthContext ของเรา จากนั้นจึงเรียกฟังก์ชันนี้ภายใน 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 ซึ่งควรจะปรากฏขึ้นหลังจากการตรวจสอบสิทธิ์สำเร็จเท่านั้น

ไปที่: screens > 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 ,
  • AppNavigator.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;

ในไฟล์ด้านบน นี่คือสิ่งที่เราทำ:

  • เรานำเข้า createStackNavigator จาก @react-navigation/stack ที่เราใช้สำหรับการนำทางสแต็กของเรา createStackNavigator ให้วิธีสำหรับแอปของคุณในการเปลี่ยนระหว่างหน้าจอโดยวางหน้าจอใหม่แต่ละหน้าจอไว้บนสแต็ก ตามค่าเริ่มต้น Stack Navigator จะได้รับการกำหนดค่าให้มีรูปลักษณ์และความรู้สึกของ iOS และ Android ที่คุ้นเคย: หน้าจอใหม่จะเลื่อนเข้ามาจากด้านขวาบน iOS และค่อยๆ จางลงจากด้านล่างของ Android คลิกที่นี่ หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ stack navigator ใน React Native
  • เราทำลายโครงสร้าง Navigator และ Screen จาก createStackNavigator()
  • ในคำสั่ง return เราสร้างการนำทางด้วย <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.js และ postAuthNavigator.js คือหน้าจอที่กำลังแสดงผล ในขณะที่อันแรกใช้ WelcomeScreen แต่ postAuthNavigator.js จะใช้ HomeScreen

ในการสร้าง AppNavigator.js เราจำเป็นต้องสร้างบางสิ่ง

เนื่องจาก AppNavigator.js เป็นที่ที่เราจะเปลี่ยนและตรวจสอบว่าเส้นทางใดที่ผู้ใช้จะสามารถเข้าถึงได้ เราจึงต้องมีหน้าจอหลายหน้าจอเพื่อให้การทำงานนี้ทำงานได้อย่างถูกต้อง เรามาสรุปสิ่งที่เราต้องสร้างกันก่อน:

  1. TransitionScreen.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 เช่นกัน
  • เราใช้ setUserToken เพื่อตั้งค่าที่ส่งคืนจาก AsyncStorage เป็น userToken ใหม่ของเรา หากค่าที่ส่งคืนเป็น null หมายความว่า userToken ของเรายังคงเป็น null
  • หลังจากบล็อก try{}…catch(){} เราตั้งค่า isLoading เป็น false เนื่องจากฟังก์ชันตรวจสอบสถานะการรับรองความถูกต้องเสร็จสมบูรณ์ เราต้องการค่าของ isLoading เพื่อทราบว่าเราควรยังคงแสดง TransitionScreen อยู่หรือไม่ ควรพิจารณาตั้งค่าข้อผิดพลาดหากมีข้อผิดพลาดในการดึงโทเค็น เพื่อให้เราสามารถแสดงปุ่ม "ลองใหม่" หรือ "ลองอีกครั้ง" ให้ผู้ใช้เห็นเมื่อพบข้อผิดพลาด
  • เมื่อใดก็ตาม AuthState ติดตั้ง เราต้องการตรวจสอบสถานะการรับรองความถูกต้อง ดังนั้นเราจึงใช้ useEffect() ReactJS เพื่อทำสิ่งนี้ เราเรียก checkAuthenticationStatus() ภายใน useEffect() hook และตั้งค่า isLoading false เมื่อเสร็จสิ้น
  • สุดท้าย เราเพิ่มสถานะของเราลงในค่า <AuthContext.Provider/> เพื่อให้เราสามารถเข้าถึงได้จากทุกที่ในแอปของเราที่ครอบคลุมโดย Context API

ตอนนี้เรามีฟังก์ชันของเราแล้ว ก็ถึงเวลาที่จะกลับไปที่ AppNavigator.js และเขียนโค้ดสำหรับติดตั้ง stack navigator โดยเฉพาะตามสถานะการตรวจสอบสิทธิ์:

การนำทาง > 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

ในกลุ่มโค้ดด้านบน ต่อไปนี้คือโครงร่างของสิ่งที่เราทำ:

  • เราได้สร้างสแตกเนวิเกเตอร์และทำลายโครงสร้าง Navigator และ Screen จากมัน
  • เรานำเข้า userToken และ isLoading จาก AuthContext . ของเรา
  • เมื่อ AuthState เมานต์ จะมีการเรียก checkAuthenticationStatus() ในเบ็ด useEffecct ที่นั่น เราใช้คำสั่ง if เพื่อตรวจสอบว่า isLoading เป็น true หรือไม่ หากเป็น true หน้าจอที่เราส่งคืนคือ <TransitionScreen /> ที่เราสร้างขึ้นก่อนหน้านี้เนื่องจาก checkAuthenticationStatus() ยังไม่สมบูรณ์
  • เมื่อ checkAuthenticationStatus() ของเราเสร็จสมบูรณ์ isLoading จะถูกตั้งค่า false และเราส่งคืนส่วนประกอบการนำทางหลักของเรา
  • NavigationContainer ถูกนำเข้าจาก @react-navigation/native ใช้เพียงครั้งเดียวในเนวิเกเตอร์หลักระดับบนสุด โปรดสังเกตว่าเราไม่ได้ใช้งานสิ่งนี้ใน preAuthNavigator.js หรือ postAuthNavigator.js
  • ใน AppNavigator() ของเรา เรายังคงสร้าง stack navigator หาก userToken ได้รับจาก Context API ของเราเป็น null เราจะเมาน PreAuthNavigator หากค่านั้นเป็นอย่างอื่น (หมายความว่า AsyncStorage.getItem() ใน checkAuthenticationStatus() คืนค่าจริง) จากนั้นเราจะเมานต์ PostAuthNavigator การเรนเดอร์แบบมีเงื่อนไขของเราทำได้โดยใช้ตัวดำเนินการ ternary

ตอนนี้เราได้ตั้งค่า AppNavigator.js แล้ว ต่อไป เราต้องส่ง AppNavigator ไปยังไฟล์ App.js

ส่ง AppNavigator ของเราไปที่ไฟล์ App.js :

App.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() เป็นฟังก์ชันแบบอะซิงโครนัสที่จะลบ user-token ออกจาก AsyncStorage ของเรา

ตอนนี้เราต้องเรียกใช้ userSignout() ใน HomeScreen.js ของเราทุกครั้งที่คลิกปุ่มออกจากระบบ

ไปที่ HomeScreen.js ของเราและใช้ userSignout() จาก AuthContext ของเรา

หน้าจอ > 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> ) } ...

ในบล็อกโค้ดด้านบนเรานำเข้า useContext hook จาก ReactJS จากนั้นเรานำเข้า AuthContext ของเรา ต่อไป เราทำลายโครงสร้างฟังก์ชัน userSignout จาก AuthContext ของเรา และฟังก์ชัน userSignout() นี้ถูกเรียกใช้ใน onLogout() ของเรา

ตอนนี้เมื่อใดก็ตามที่คลิกปุ่มออกจากระบบ โทเค็นผู้ใช้ใน AsyncStorage ของเราจะถูกล้าง

โว้ว! กระบวนการทั้งหมดของเราเสร็จสิ้น

นี่คือสิ่งที่จะเกิดขึ้นเมื่อคุณกดปุ่มย้อนกลับหลังจากที่คุณเข้าสู่ระบบ:

กดปุ่มย้อนกลับหลังจากเข้าสู่แอพ

นี่คือสิ่งที่จะเกิดขึ้นเมื่อคุณกดปุ่มย้อนกลับหลังจากออกจากระบบ:

กดปุ่มย้อนกลับหลังจากออกจากระบบแอพ

ต่อไปนี้คือพฤติกรรมบางอย่างที่เราสังเกตเห็นเมื่อใช้รูปแบบนี้ในการสลับสแต็กการนำทางของเรา:

  1. คุณจะสังเกตเห็นว่าไม่มีที่ไหนที่เราจำเป็นต้องใช้ navigation.navigate() หรือ navigation.push() เพื่อไปยังเส้นทางอื่นหลังจากเข้าสู่ระบบ เมื่อสถานะของเราได้รับการอัปเดตด้วยโทเค็นผู้ใช้ การแสดงสแต็กการนำทางจะเปลี่ยนไปโดยอัตโนมัติ
  2. การกดปุ่มย้อนกลับบนอุปกรณ์ของคุณหลังจากเข้าสู่ระบบสำเร็จแล้วจะไม่สามารถนำคุณกลับไปที่หน้าการเข้าสู่ระบบได้ แต่จะเป็นการปิดแอปทั้งหมดแทน ลักษณะการทำงานนี้มีความสำคัญเนื่องจากคุณไม่ต้องการให้ผู้ใช้สามารถกลับไปที่หน้าเข้าสู่ระบบได้ เว้นแต่จะออกจากระบบแอป เช่นเดียวกับการออกจากระบบ เมื่อผู้ใช้ออกจากระบบแล้ว จะไม่สามารถใช้ปุ่มย้อนกลับเพื่อกลับไปยัง HomeScreen จอหลักได้ แต่แอปจะปิดลงแทน

บทสรุป

ในหลาย ๆ แอพ การตรวจสอบสิทธิ์เป็นส่วนที่สำคัญที่สุดเพราะเป็นการยืนยันว่าบุคคลที่พยายามเข้าถึงเนื้อหาที่ได้รับการคุ้มครองมีสิทธิ์ในการเข้าถึงข้อมูล การเรียนรู้วิธีทำให้ถูกต้องเป็นขั้นตอนสำคัญในการสร้างแอปพลิเคชัน/การนำทางที่ยอดเยี่ยม ใช้งานง่าย และใช้งานง่าย

ต่อจากโค้ดนี้ ต่อไปนี้คือบางสิ่งที่คุณอาจพิจารณาเพิ่ม:

  • การตรวจสอบแบบฟอร์มสำหรับตรวจสอบช่องป้อนข้อมูล ตรวจสอบการตรวจสอบความถูกต้องของแบบฟอร์ม React Native ด้วย Formik และ Yup
  • การตรวจสอบสิทธิ์ Firebase สำหรับการรวมการตรวจสอบสิทธิ์กับ Gmail, Github, Facebook, Twitter หรืออินเทอร์เฟซที่กำหนดเองของคุณ ลองใช้ React Native Firebase
  • แนวคิดโค้ดสำหรับนักออกแบบ: การพิสูจน์ตัวตนและการอนุญาต

ต่อไปนี้คือแหล่งข้อมูลสำคัญบางส่วนที่ฉันพบว่าจะช่วยให้คุณเข้าใจมากขึ้นเกี่ยวกับการรับรองความถูกต้อง ความปลอดภัย และวิธีดำเนินการอย่างถูกต้อง:

ทรัพยากร

  • React Native: อธิบายขั้นตอนการตรวจสอบผู้ใช้
  • 10 React Security แนวทางปฏิบัติที่ดีที่สุด
  • วิธีการตรวจสอบสิทธิ์ที่สามารถป้องกันการละเมิดครั้งต่อไปได้
  • ดูบิลด์ / ดูตัวอย่างแอปพลิเคชันของเราที่นี่;
  • ดูโครงการบน GitHub