معالجة تصاعد وإلغاء تثبيت مسارات الملاحة في React Native
نشرت: 2022-03-10في هذه المقالة ، سنستعرض طرق التنقل المتصاعدة وإلغاء تركيبها في React Native. السلوك المتوقع لتطبيقك هو أنه بمجرد استيفاء شرط المصادقة ، تتوفر مجموعة جديدة من مسارات التنقل فقط للمستخدمين الذين قاموا بتسجيل الدخول ، في حين أن الشاشات الأخرى التي تم عرضها قبل إزالة المصادقة ولا يمكن إرجاعها إليها ما لم يقوم المستخدم بتسجيل الخروج من التطبيق.
للأمان في تطبيقك ، توفر لك المسارات المحمية طريقة لعرض معلومات / محتوى معين فقط على تطبيقك لمستخدمين محددين ، مع تقييد الوصول من الأشخاص غير المصرح لهم.
سنعمل مع Expo لهذا المشروع لأنه سيساعدنا في التركيز على المشكلة المطروحة بدلاً من القلق بشأن الكثير من الإعدادات. يمكن اتباع نفس الخطوات بالضبط في هذه المقالة لتطبيق React Native العاري.
أنت بحاجة إلى بعض الإلمام بـ JavaScript و React Native لمتابعة هذا البرنامج التعليمي. إليك بعض الأشياء المهمة التي يجب أن تكون على دراية بها بالفعل:
- المكونات المخصصة في React Native (كيفية إنشاء المكونات واستلامها وتمريرها واستخدامها في أحد المكونات). اقرأ أكثر.
- رد فعل الملاحة. اقرأ أكثر.
- Stack Navigator في React Native. اقرأ أكثر.
- المعرفة الأساسية لمكونات React Native Core (
<View/>
،<Text/>
، إلخ). اقرأ أكثر. - تفاعل
AsyncStorage
الأصلي. اقرأ أكثر. - السياق API. اقرأ أكثر.
إعداد المشروع والمصادقة الأساسية
إذا كنت جديدًا في استخدام إكسبو ولا تعرف كيفية تثبيت إكسبو ، فقم بزيارة الوثائق الرسمية. بمجرد اكتمال التثبيت ، امض قدمًا لتهيئة مشروع React Native جديد مع expo من موجه الأوامر الخاص بنا:
expo init navigation-project
سيتم تقديمك مع بعض الخيارات لاختيار الطريقة التي تريد أن يكون الإعداد الأساسي بها:
في حالتنا ، دعنا نحدد الخيار الأول لإعداد مشروعنا كمستند فارغ. الآن ، انتظر حتى يكتمل تثبيت تبعيات JavaScript.
بمجرد إعداد تطبيقنا ، يمكننا تغيير دليلنا إلى دليل مشروعنا الجديد وفتحه في محرر الكود المفضل لديك. نحتاج إلى تثبيت المكتبة التي سنستخدمها لـ AsyncStorage
ومكتبات التنقل الخاصة بنا. داخل مجلد المجلد في الجهاز الطرفي ، الصق الأمر أعلاه واختر نموذجًا (سيعمل blank
) لتثبيت تبعيات مشروعنا.
لنلقِ نظرة على الغرض من كل من هذه التبعيات:
- @ رد فعل المجتمع الأصلي / تخزين غير متزامن
مثل localStorage على الويب ، فهي واجهة برمجة تطبيقات أصلية من React لاستمرار البيانات على جهاز في أزواج مفتاح - قيمة. - @ رد فعل المجتمع الأصلي / عرض مقنع ، رد فعل الشاشات الأصلية ، رد فعل أصلي لفتة مقبض
هذه التبعيات هي أدوات مساعدة أساسية يستخدمها معظم الملاحين لإنشاء بنية التنقل في التطبيق. (اقرأ المزيد في بدء استخدام التنقل الأصلي في React.) - @ رد فعل التنقل / أصلي
هذه هي التبعية لـ React Native navigation. - @ رد فعل التنقل / المكدس
هذه هي التبعية للتنقل المكدس في 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
من دليل التطبيق في جهازك الطرفي. بمجرد بدء تشغيل التطبيق ، يمكنك استخدام تطبيق expo من هاتفك المحمول لمسح الرمز الشريطي وعرض التطبيق ، أو إذا كان لديك محاكي android / محاكي IOS ، يمكنك فتح التطبيق من خلالها من أداة مطور المعرض التي يفتح في متصفحك عند بدء تطبيق المعرض. بالنسبة لأمثلة الصور في هذه المقالة ، سنستخدم 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
في الجزء السفلي من الكود.
الآن وقد انتهينا من هذا ، دعنا نجعل هذا المكون يعمل كما هو متوقع باستخدام خطاف useState
لتخزين قيم المدخلات وتحديث حالاتها في أي وقت يحدث تغيير في حقول الإدخال. سنجلب أيضًا استيراد الخطاف useCallback
من 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 ، دعنا نمضي قدمًا ونبدأ العمل مع Context API لإدارة حالتنا العالمية.
لماذا السياق 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 على منطق واجهة برمجة تطبيقات السياق وقيم الحالة الخاصة بها. يمكن استدعاء الوظائف المكتوبة هنا من أي مكان في تطبيقنا وعندما تقوم بتحديث القيم في الحالة ، يتم تحديثها عالميًا أيضًا.
أولاً ، لنحضر جميع الواردات التي سنحتاجها في هذا الملف:
السياق> 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 تتيح لك الاحتفاظ بالبيانات دون اتصال بالإنترنت عبر الجهاز في تطبيق 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()
بنا. هذه الوظيفة هي وظيفة غيرwelcomeScreen.jsx
async
لن يتم استدعاء هذه الوظيفة إلا إذا كان البريد الإلكتروني وكلمة المرور اللذين قدمهما المستخدم يطابقان كائن تفاصيل المستخدم الصحيح الذي قدمناه. عادةً ما يحدث أثناء المصادقة هو إنشاء رمز مميز للمستخدم بعد مصادقة المستخدم على الواجهة الخلفية باستخدام حزمة مثل 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 الذي من المفترض أن يظهر فقط بعد مصادقة ناجحة.
انتقل إلى: الشاشات> 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
طريقة لتطبيقك للانتقال بين الشاشات حيث يتم وضع كل شاشة جديدة أعلى حزمة. بشكل افتراضي ، يتم تكوين متصفح المكدس ليحصل على الشكل والمظهر المألوفين لنظامي التشغيل iOS و Android: تنزلق الشاشات الجديدة من اليمين على نظام iOS ، وتتلاشى من الأسفل على Android. انقر هنا إذا كنت تريد معرفة المزيد عن متصفح المكدس في React Native. - لقد دمرنا
Navigator
Screen
منcreateStackNavigator()
. - في بيان العودة الخاص بنا ، أنشأنا التنقل باستخدام
<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 هو المكان الذي سنقوم بالتبديل فيه والتحقق من المسار الذي سيكون متاحًا للوصول إليه من قبل المستخدم ، فنحن بحاجة إلى عدة شاشات حتى يعمل هذا بشكل صحيح ، دعنا نحدد الأشياء التي نحتاج إلى إنشائها أولاً:
- TransitionScreen.js
أثناء تحديد التطبيق للتنقل الذي سيتم تحميله ، نريد ظهور شاشة انتقال. عادةً ما تكون شاشة الانتقال عبارة عن قرص تحميل أو أي رسوم متحركة مخصصة أخرى يتم اختيارها للتطبيق ، ولكن في حالتنا ، سنستخدم علامة<Text/>
أساسية لعرضloading…
. -
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()
قيمةisLoading
علىfalse
عند الانتهاء. - أخيرًا ، نضيف حالاتنا إلى قيم
<AuthContext.Provider/>
الخاصة بنا حتى نتمكن من الوصول إليها من أي مكان في تطبيقنا المشمول بواجهة برمجة تطبيقات السياق.
الآن بعد أن أصبح لدينا وظيفتنا ، حان الوقت للعودة إلى AppNavigator.js وكتابة الكود الخاص بتركيب متصفح مكدس معين بناءً على حالة المصادقة:
التنقل> AppNavigator.js
أولاً ، سنستورد كل ما نحتاجه لـ AppNavigator.js .
import React, { useEffect, useContext } from "react"; import PreAuthNavigator from "./preAuthNavigator"; import PostAuthNavigator from "./postAuthNavigator"; import { NavigationContainer } from "@react-navigation/native" import { createStackNavigator } from "@react-navigation/stack"; import AuthContext from "../../context/authContext/AuthContext"; import TransitionScreen from "../screens/TransitionScreen";
الآن بعد أن أصبح لدينا جميع وارداتنا ، فلنقم بإنشاء وظيفة AppNavigator()
.
... const AppNavigator = () => { } export default AppNavigator
بعد ذلك ، سنمضي قدمًا في كتابة محتوى وظيفة AppNavigator()
الخاصة بنا:
import React, { useState, useEffect, useContext } from "react"; import PreAuthNavigator from "./preAuthNavigator"; import PostAuthNavigator from "./postAuthNavigator"; import { NavigationContainer } from "@react-navigation/native" import { createStackNavigator } from "@react-navigation/stack"; import AuthContext from "../../context/authContext/AuthContext"; import TransitionScreen from "../screens/transition"; const AppNavigator = () => { const { Navigator, Screen } = createStackNavigator(); const authContext = useContext(AuthContext); const { userToken, isLoading } = authContext; if(isLoading) { return <TransitionScreen /> } return ( <NavigationContainer> <Navigator> { userToken == null ? ( <Screen name="PreAuth" component={PreAuthNavigator} options={{ header: () => null }} /> ) : ( <Screen name="PostAuth" component={PostAuthNavigator} options={{ header: () => null }} /> ) } </Navigator> </NavigationContainer> ) } export default AppNavigator
في الجزء العلوي من الكود ، إليك مخطط لما فعلناه:
- قمنا بإنشاء متصفح مكدس ودمرنا
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()
، ما زلنا ننشئ متصفح مكدس. إذا كانuserToken
الذي تم الحصول عليه من واجهة برمجة تطبيقات السياق الخاصة بناnull
، فإننا نقوم بتركيبPreAuthNavigator
، إذا كانت قيمته شيئًا آخر (بمعنى أنAsyncStorage.getItem()
فيcheckAuthenticationStatus()
أعاد قيمة فعلية) ، فسنقوم بتركيبPostAuthNavigator
. يتم إجراء التصيير الشرطي باستخدام عامل التشغيل الثلاثي.
الآن قمنا بإعداد AppNavigator.js الخاص بنا. بعد ذلك ، نحتاج إلى تمرير AppNavigator
إلى ملف App.js الخاص بنا.
لنمرر AppNavigator
الخاص بنا إلى ملف App.js :
App.js
... import AppNavigator from './views/navigation/AppNavigator'; ... return ( <AuthState> <AppNavigator /> </AuthState> );
دعنا الآن نرى كيف يبدو تطبيقنا في الوقت الحالي:
إليك ما يحدث عند تقديم بيانات اعتماد غير صحيحة أثناء محاولة تسجيل الدخول:
إضافة وظيفة تسجيل الخروج
في هذه المرحلة ، اكتملت عملية المصادقة واختيار المسار. الشيء الوحيد المتبقي لتطبيقنا هو إضافة وظيفة تسجيل الخروج.
زر تسجيل الخروج موجود في ملف HomeScreen.js . لقد مررنا وظيفة onLogout 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
من ReactJS ، ثم قمنا باستيراد AuthContext الخاص بنا. بعد ذلك ، قمنا بتدمير وظيفة userSignout
من AuthContext
الخاصة بنا ويتم استدعاء وظيفة userSignout()
onLogout()
في وظيفة onLogout () الخاصة بنا.
الآن عندما يتم النقر فوق زر تسجيل الخروج الخاص بنا ، يتم مسح رمز المستخدم في AsyncStorage
بنا.
هاهو! تم الانتهاء من العملية برمتها.
إليك ما يحدث عند الضغط على زر الرجوع بعد تسجيل الدخول:
إليك ما يحدث عند الضغط على زر الرجوع بعد تسجيل الخروج:
فيما يلي بعض السلوكيات المختلفة التي نلاحظها عند استخدام هذا النمط في تبديل حزمة التنقل الخاصة بنا:
- ستلاحظ أنه لم يكن هناك مكان نحتاج إليه للاستفادة من
navigation.navigate()
أوnavigation.push()
للانتقال إلى طريق آخر بعد تسجيل الدخول. بمجرد تحديث حالتنا برمز المستخدم ، يتم تغيير مكدس التنقل الذي تم تقديمه تلقائيًا. - الضغط على زر الرجوع على جهازك بعد نجاح تسجيل الدخول لا يمكن أن يعيدك إلى صفحة تسجيل الدخول ، وبدلاً من ذلك ، فإنه يغلق التطبيق بالكامل. هذا السلوك مهم لأنك لا تريد أن يتمكن المستخدم من العودة إلى صفحة تسجيل الدخول إلا إذا قام بتسجيل الخروج من التطبيق. ينطبق الشيء نفسه على تسجيل الخروج - بمجرد تسجيل المستخدم للخروج ، لا يمكنه استخدام زر الرجوع للعودة إلى شاشة الشاشة
HomeScreen
، ولكن بدلاً من ذلك ، يتم إغلاق التطبيق.
خاتمة
في العديد من التطبيقات ، تعد المصادقة أحد أهم الأجزاء لأنها تؤكد أن الشخص الذي يحاول الوصول إلى المحتوى المحمي له الحق في الوصول إلى المعلومات. يعد تعلم كيفية القيام بذلك بشكل صحيح خطوة مهمة في بناء تطبيق رائع وبديهي وسهل الاستخدام / التنقل.
بناءً على هذا الرمز ، إليك بعض الأشياء التي قد تفكر في إضافتها:
- التحقق من صحة النموذج للتحقق من صحة حقول الإدخال. تحقق من التحقق من صحة النموذج الأصلي من React مع Formik و Yup.
- مصادقة Firebase لدمج المصادقة مع Gmail أو Github أو Facebook أو Twitter أو واجهتك المخصصة. تحقق من React Native Firebase.
- مفاهيم الكود للمصممين: المصادقة والترخيص.
إليك أيضًا بعض الموارد المهمة التي وجدتها والتي ستوضح لك المزيد حول المصادقة والأمان وكيفية القيام بذلك بشكل صحيح:
موارد
- رد الفعل الأصلي: شرح تدفق مصادقة المستخدم
- أفضل 10 ممارسات أمان في React
- طرق المصادقة التي يمكن أن تمنع الخرق التالي
- عرض بناء / معاينة مباشرة لتطبيقنا هنا ؛
- اعرض المشروع على جيثب.