دليل شامل: إدارة التنقل في React Native باستخدام react-navigation 5

دقائق القراءة: 7

تُعدّ مكتبة react-navigation الخيار الأمثل والأكثر شيوعًا لإدارة التنقل (Navigation) في تطبيقات React Native. لطالما كانت هذه المكتبة هي الحل الأول الذي يتبادر إلى الذهن عند الحديث عن بناء تجربة مستخدم سلسة وفعالة في تطبيقات الجوال. ويعود الفضل في ذلك جزئيًا إلى واجهة برمجية (API) سهلة الاستخدام وقابلة للتخصيص بدرجة عالية.

مع انتقال الإصدار الخامس من react-navigation من مرحلة البيتا إلى الإصدار المستقر، شهدت المكتبة تحولات جوهرية في الميزات وتصميم واجهة برمجية جديدة تمامًا. هذا التصميم يقدم طريقة أبسط وأكثر ديناميكية لتعريف المسارات (Routes) وإدارة تدفق التطبيق. في هذا المقال، سنتعمق في استكشاف واجهات البرمجة الجديدة هذه، ونتعرف على أفضل السبل لاستخدامها في مشاريعنا وتطبيقاتنا.

تثبيت مكتبة react-navigation 5

طرأت بعض التغييرات الطفيفة على طريقة تثبيت react-navigation في الإصدار الخامس مقارنة بالإصدارات السابقة (مثل 4.x). إليك الخطوات التفصيلية:

تثبيت الإصدارات القديمة (قبل 5.x)

في الإصدارات التي سبقت 5.x، كان التثبيت يتم عادةً بالشكل التالي:

// > 4.x versions
yarn add react-navigation

تثبيت الإصدار الخامس (5.x وما بعده)

لتثبيت react-navigation 5، ستحتاج إلى تثبيت الحزمة الأساسية @react-navigation/native:

// باستخدام yarn
yarn add @react-navigation/native

// باستخدام npm
npm install @react-navigation/native

تعتمد الإصدارات الحديثة من react-navigation على العديد من المكتبات الخارجية (Third-party libraries) لدعم ميزات مثل الرسوم المتحركة ومعالجة الانتقالات. لذلك، من الضروري دائمًا تثبيت هذه المكتبات التابعة (Peer Dependencies) لضمان عمل المكتبة بشكل صحيح:

// باستخدام yarn
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

// باستخدام npm
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

بعد تثبيت هذه الحزم، قد تحتاج إلى ربطها (link) بمشروعك الأصلي، خاصة في بيئات iOS و Android، وذلك باتباع الإرشادات الرسمية لكل مكتبة، أو باستخدام npx react-native link في المشاريع الأقدم، أو الاعتماد على الربط التلقائي في الإصدارات الأحدث من React Native.

الشاشات الديناميكية: مرونة في تعريف المسارات

يقدم الـ API الجديد ديناميكية غير مسبوقة في تهيئة المسارات (Routes) والشاشات. في السابق، كان تعريف المسارات يتم بشكل ثابت، حيث كنا نضطر إلى تحديد جميع المسارات في ملف تهيئة (Config file) مسبقًا.

النهج القديم (الإصدارات < 4.x)

في الإصدارات السابقة، كان تعريف المسارات يبدو كالتالي، حيث يتم استيراد الشاشات وتجميعها في كائن ثابت:

 // @flow
 import React from "react" ;
 import { createAppContainer, createSwitchNavigator } from "react-navigation" ;
 import { createStackNavigator } from "react-navigation-stack" ;

 /** ---------Screens----------- */
 // import LaunchScreen from "../Containers/LaunchScreen";
 import HomeScreen from "../Containers/HomeScreen" ;
 import ProfileScreen from "../Containers/ProfileScreen" ;
 import LoginScreen from "../Containers/LoginScreen" ;

 const StackNavigator = createStackNavigator(
   { initialRouteName : "Home" },
   {
     Home : { screen : HomeScreen },
     Login : { screen : LoginScreen, headerMode : "none" , },
     Profile : { screen : ProfileScreen }
   }
 );

 export default createAppContainer(StackNavigator);

النهج الجديد (الإصدار 5)

يأتي الـ API الجديد بمكونات ديناميكية تجعل التنقل أكثر مرونة. الطريقة الجديدة لتعريف المسارات تشبه إلى حد كبير طريقة عمل مكتبة react-router في الويب، حيث يتم تعريف الشاشات كمكونات داخل مكون التنقل الرئيسي:

 import React from "react"
 import { SafeAreaView, StyleSheet, View, Text, StatusBar } from "react-native"
 import { NavigationContainer } from "@react-navigation/native"
 import { createStackNavigator } from "@react-navigation/stack"

 const App: () => React$Node = () => {
   return (
     <>
       < StatusBar barStyle = "dark-content" />
       < SafeAreaView style = {styles.containerStyle} >
         < AppNavigation />
       </ SafeAreaView >
     </>
   )
 }

 const Stack = createStackNavigator()
 const AppNavigation = () => {
   return (
     < NavigationContainer >
       < Stack.Navigator initialRouteName = "home" >
         < Stack.Screen name = "home" component = {HomeScreen} />
       </ Stack.Navigator >
     </ NavigationContainer >
   )
 }

 const HomeScreen = () => {
   return (
     < View style = {styles.containerStyle} >
       < Text style = {styles.title} > Home Screen </ Text >
     </ View >
   )
 }

مثال على التنقل الديناميكي في React Native باستخدام react-navigation 5

هذا النهج الجديد أكثر ديناميكية، وأبسط في الاستخدام، ويوفر تجربة تطوير أكثر سلاسة، خاصة للمطورين المعتادين على أنماط توجيه مماثلة في بيئات أخرى.

الخيارات الديناميكية: تخصيص التنقل لحظة بلحظة

لطالما كانت ميزة الخيارات الديناميكية هي الأكثر طلبًا من قبل مجتمع react-navigation. في الإصدارات السابقة، كان تغيير سلوك التنقل بشكل ديناميكي يمثل تحديًا كبيرًا.

النهج القديم (الإصدارات < 4.x)

مع الإصدارات الأقدم من react-navigation، كان علينا تعريف الخيارات (Options) بشكل ثابت لكل شاشة، ولم يكن هناك طريقة مباشرة لتغيير هذه الخيارات ديناميكيًا أثناء تشغيل التطبيق:

 static navigationOptions = {
   title : "Sign In" ,
   header : null ,
   mode : "modal" ,
   headerMode : "none"
 };

النهج الجديد (الإصدار 5)

يأتي react-navigation 5 بنهج ديناميكي وبسيط للغاية. يمكننا الآن تعيين الخيارات لأي شاشة باستخدام خاصية options مباشرة داخل مكون Stack.Screen، مما يتيح لنا الوصول إلى props وتحديد الخيارات بناءً على حالة التطبيق:

 const AppNavigation = ( {} ) => {
   let auth = {
     authenticated : true ,
     user : {
       email : "user@mail.com" ,
       username : "John" ,
     },
   }
   let ProfileScreenTitle = auth.authenticated ? auth.user.username : "Profile"
   return (
     < NavigationContainer >
       < Stack.Navigator initialRouteName = "Home" >
         < Stack.Screen name = "Home" component = {HomeScreen} />
         < Stack.Screen name = "Profile" component = {ProfileScreen} options = {{
           title: ProfileScreenTitle ,
           headerTintColor: "# 4aa3ba ",
           headerStyle: {
             backgroundColor: darkModeOn ? "# 000 " : "# fff ",
           },
         }} />
         < Stack.Screen name = "About" component = {AboutScreen} />
       </ Stack.Navigator >
     </ NavigationContainer >
   )
 }

مثال على تخصيص شريط العنوان ديناميكياً في React Native

بفضل الخيارات الديناميكية، يمكننا تغيير عنوان الشاشة بناءً على حالة المصادقة (Authentication)، فمثلاً، إذا كان المستخدم مسجلاً للدخول، يمكننا تعيين عنوان الشاشة ليكون اسم المستخدم. كما يمكننا تغيير لون خلفية شريط العنوان (Header) بناءً على نمط التطبيق (مثل الوضع الداكن أو الفاتح). هذه المرونة مفيدة للغاية، خاصة عند بناء تطبيقات تدعم سمات ديناميكية أو وضعًا داكنًا.

خطافات React (Hooks): تبسيط الوصول إلى API التنقل

تُعدّ خطافات React Hooks من أبرز الميزات الجديدة والمفضلة في react-navigation 5، فهي توفر الكثير من الوقت والجهد. قدم الـ API الجديد مجموعة من الخطافات المخصصة لأداء إجراءات معينة بسهولة.

في الإصدارات السابقة، على سبيل المثال، إذا أردنا الحصول على اسم الشاشة النشطة حاليًا، كان علينا إنشاء دوال مساعدة (Helpers) للقيام بذلك، وهو ما كان يتطلب كودًا إضافيًا ومعقدًا بعض الشيء:

 export function getCurrentRouteName ( ): string | null {
   const tag = "[getCurrentRouteNameSync] "
   const navState = getStore().getState().nav
   const currentRoute = getActiveRouteState(navState)
   console .log(tag + " currentRoute > " , currentRoute)
   return currentRoute && currentRoute.routeName ? currentRoute.routeName : null
 }

الآن، تُجنبنا واجهة Hooks API كل هذه التعقيدات وتجعل الوصول إلى Navigation API أسهل بكثير، غالبًا بسطر واحد من الكود. يمكننا الآن الحصول على اسم المسار (RouteName) بسهولة باستخدام الخطاف useRoute:

الوصول إلى اسم المسار الحالي باستخدام useRoute

يوفر الخطاف useRoute كائن المسار الحالي الذي يحتوي على معلومات مثل اسم المسار والبارامترات:

 import { useRoute } from "@react-navigation/native"

 const AboutScreen = ( { navigation } ) => {
   const route = useRoute()
   return (
     < View style = {{ justifyContent: " space-around ", flex: 1 , alignItems: " center ", }} >
       {/* Display the RouteName here */}
       < Text style = {styles.title} > {route.name} </ Text >
     </ View >
   )
 }

الوصول إلى حالة التنقل باستخدام useNavigationState

يمكننا القيام بنفس الشيء مع الخطاف useNavigationState، والذي يمنحنا وصولاً مباشرًا إلى حالة التنقل الكاملة (Navigation State)، مما يتيح لنا فحص تفاصيل مثل فهرس الشاشة النشطة وعدد المسارات:

 const navigationState = useNavigationState( state => state)
 let index = navigationState.index
 let routes = navigationState.routes.length
 console .log(index)
 console .log(routes)

خطافات إضافية مفيدة

تقدم react-navigation خطافات أخرى قوية ومفيدة، على سبيل المثال:

  • useFocusEffect: خطاف تأثير جانبي (Side Effect Hook) يعيد الشاشة المركزة (Focused Screen) عند تحميل الشاشات أو التركيز عليها.
  • useLinking: يتعامل مع الروابط العميقة (Deep Linking)، مما يتيح لتطبيقك الاستجابة لروابط URL خارجية.

نوصي بشدة بالاطلاع على الوثائق الرسمية لاستكشاف هذه الخطافات وغيرها والاستفادة القصوى منها في مشاريعك.

خاتمة موجزة

لقد انتقل الـ API الجديد لمكتبة react-navigation بشكل حاسم من النهج الثابت إلى النهج الديناميكي. هذا التوجه يمثل قفزة نوعية ستغير بلا شك طريقة تعاملنا مع التنقل في تطبيقات React Native. كانت المسارات الديناميكية مطلبًا رئيسيًا لمستخدمي react-navigation، وهذا النهج الجديد سيساعدنا على بناء تجربة تنقل أفضل وأكثر مرونة للمستخدمين.

للمزيد من المحتوى حول React Native، يمكنك زيارة المصادر الموثوقة والمدونات التقنية المتخصصة.

الخلاصة التقنية

يمثل الإصدار الخامس من react-navigation نقطة تحول مهمة في تطوير تطبيقات React Native. لقد نجحت المكتبة في تبسيط واجهة برمجة التطبيقات (API) بشكل كبير، وجعلت من عملية تعريف المسارات وإدارة خيارات التنقل أكثر ديناميكية ومرونة. التحول نحو استخدام المكونات كشاشات مباشرة، وتقديم خطافات React Hooks للوصول السهل إلى حالة التنقل، يعزز من إنتاجية المطورين ويقلل من التعقيد. هذه التغييرات لا تجعل المكتبة أقوى فحسب، بل تجعلها أيضًا أكثر سهولة في التعلم والاستخدام، مما يفتح الباب أمام بناء تجارب مستخدم أكثر تفاعلية وتخصيصًا.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *