التنقل بين الشاشات في React Native

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

نادرًا ما تتكون تطبيقات الجوال من شاشة واحدة فقط. عادةً ما يُدار عرض شاشاتٍ متعدّدة والتحويل بينها بما يعرف بالمتنقّل (navigator).

يغطي هذا الدليل مكونات التنقّل المتوفرة في React Native. إذا كان مفهوم التنقّل جديدًا عليك، فربما من الأفضل أن تستخدم مكتبة React Navigation التي توفّر حلًّا سهل الاستخدام لإدارة التنقّل بين الشاشات، مع القدرة على استخدام نمطي التنقل المُكدَّس (stack navigation) والتنقل المبوب (tabbed navigation) الشائعين على كل من نظامي التشغيل iOS وAndroid.

إذا كنت تستهدف نظام التشغيل iOS فقط، فانظر NavigatorIOS لطريقةٍ توفِّر مظهرًا أصيلًا سهلَ الإعداد، إذ يُوفّر غلافًا (wrapper) حول الصّنف الأصيل ‎UINavigationController‎. لكنّ هذا المكون لن يعمل على Android.

إذا أردت مظهرًا أصيلًا على كل من نظامي التشغيل iOS وAndroid، أو إذا كنت بصدد دمج React Native مع تطبيق أصيل يعمل بالفعل على إدارة التنقّل، فمكتبة react-native-navigation توفر تنقّلًا أصيلًا على كلا النظامين.

React Navigation

الحل الذي يتبنّاه مجتمع المطورين هو مكتبةٌ قائمة بذاتها تسمح للمطورين بإعداد شاشات التطبيق باستخدام بضعة أسطر من الشيفرة.

الخطوة الأولى هي تثبيتها في مشروعك:

npm install --save react-navigation

يمكنك بعد ذلك إنشاء تطبيقٍ بسرعة باستخدام شاشة رئيسية وشاشة ملف شخصي كالتالي:

import {createStackNavigator, createAppNavigator} from 'react-navigation';

const MainNavigator = createStackNavigator({
  Home: {screen: HomeScreen},
  Profile: {screen: ProfileScreen},
});

const App = createAppNavigator(MainNavigator);

export default App;

يمكن لكل مكوّن شاشةٍ تعيين خيارات التنقل مثل عنوان الترويسة (header). يمكن للمكتبة استخدام منشئي تأثيرات (action creators) على خاصيّة ‎navigation‎ لإنشاء روابط توصِل إلى شاشاتٍ أخرى (انظر الدالةَ ‎navigate()‎‎ التي استُخرِجَت من ‎this.props.navigation‎ أسفله):

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const {navigate} = this.props.navigation;
    return (
      <Button
        title="Go to Jane's profile"
        onPress={() => navigate('Profile', {name: 'Jane'})}
      />
    );
  }
}

تُسهِّل موجّهات (routers) مكتبةِ React Navigation الهيمنة على (override) آليّة عمل التنقل. ولأنّ الموجّهات قابلة للتّداخل (nested) داخل بعضها البعض، فيمكن للمطورين تغيير منطق التنقل في منطقة واحدة من التطبيق دون إجراء تغييرات واسعة النطاق.

تستخدم عروضُ React Navigation مكوّناتٍ أصيلة مع مكتبة التحريك Animated لتقديم تحريكاتِ 60 إطارًا في الثانية (60fps) تُشغَّل على السلسلة الأصيلة (native thread). إضافةً إلى إمكانيّة تخصيص التحريكات والإيماءات بسهولة.

لمقدمة كاملة حول React Navigation، اتبع دليل React Navigation، أو تصفح توثيقات أخرى كهذه الصفحة.

المكوّن ‎NavigatorIOS

يبدو المكوّن ‎NavigatorIOS‎ مطابقًا للصنف UINavigationController، وهذا لأنه مبنيّ عليه.

NavigationStack-NavigatorIOS.gif

مثال:

<NavigatorIOS
  initialRoute={{
    component: MyScene,
    title: 'My Initial Scene',
    passProps: {myProp: 'foo'},
  }}
/>

يستخدم ‎NavigatorIOS‎ الموجّهات (routes) لتمثيل الشاشات بشكل مشابهٍ لأنظمة التنقل الأخرى، مع بعض الاختلافات المهمة. يمكن تحديد المكون الفعلي الذي سيُصيَّر بمفتاح ‎component‎ في الموجّه، ويمكن تحديد أي خاصيّاتٍ لتُمرَّر إلى هذا المكون داخل ‎passProps‎. سيُمرَّرُ كائنُ ‎navigator‎ تلقائيًا كخاصيّةٍ للمكوّن، ما يسمح لك باستدعاء كل من ‎push‎ و‎pop‎ حسب الحاجة.

لأنّ المكوّن ‎NavigatorIOS‎ يعتمد على آليات التّنقل التي توفِّرها أدوات UIKit الأصيلة، فسيعرض تلقائيًا شريط تنقّلٍ مع عنوانٍ وزر رجوع.

import React from 'react';
import PropTypes from 'prop-types';
import {Button, NavigatorIOS, Text, View} from 'react-native';

export default class NavigatorIOSApp extends React.Component {
  render() {
    return (
      <NavigatorIOS
        initialRoute={{
          component: MyScene,
          title: 'My Initial Scene',
          passProps: {index: 1},
        }}
        style={{flex: 1}}
      />
    );
  }
}

class MyScene extends React.Component {
  static propTypes = {
    route: PropTypes.shape({
      title: PropTypes.string.isRequired,
    }),
    navigator: PropTypes.object.isRequired,
  };

  constructor(props, context) {
    super(props, context);
    this._onForward = this._onForward.bind(this);
  }

  _onForward() {
    let nextIndex = ++this.props.index;
    this.props.navigator.push({
      component: MyScene,
      title: 'Scene ' + nextIndex,
      passProps: {index: nextIndex},
    });
  }

  render() {
    return (
      <View>
        <Text>Current Scene: {this.props.title}</Text>
        <Button
          onPress={this._onForward}
          title="Tap me to load the next scene"
        />
      </View>
    );
  }
}

انظر توثيق NavigatorIOS للمزيد من المعلومات حول هذا المكون.

مصادر