ReactNative/intro react

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

أساسيات React

يُشغَّل إطار عمل React Native على React، وهي مكتبة شائعة ومفتوحة المصدر تُستخدَم لبناء واجهات المستخدم باستخدام لغة JavaScript. يجب فهم React فهمًا جيدًا لتحقيق أقصى استفادة من React Native. تساعدك هذه الصفحة للبدء أو لاستذكار المفاهيم الأساسية من React والتي هي:

  • المكونات components
  • JXC
  • props
  • state

يمكنك الاطلاع على توثيق React، إن أردت التعمق أكثر.

المكوّن الأول

يستخدم المثال التالي المكون Cat:

مكون الدالة Function component

import React from 'react';
import { Text } from 'react-native';

const Cat = () => {
  return (
    <Text>Hello, I am your cat!</Text>
  );
}

export default Cat;

مكون الصنف Class component

تميل مكونات الصنف إلى تكون أطول من مكونات الدالة.

import React, { Component } from 'react';
import { Text } from 'react-native';

class Cat extends Component {
  render() {
    return (
      <Text>Hello, I am your cat!</Text>
    );
  }
}

export default Cat;

يمكنك أيضًا استيراد مكون Component من React كما يلي:

import React, { Component } from 'react';

يبدأ المكون كصنفٍ يرث Component بدلًا من أن يكون كدالة:

class Cat extends Component {}

لمكونات الصنف دالةٌ render() function، ويُخرَج كل ما تعيده هذه الدالة كعنصر React:

class Cat extends Component {
  render() {
    return <Text>Hello, I am your cat!</Text>;
  }
}

يمكنك تصدير مكون الصنف كما هو الحال مع مكونات الدالة:

class Cat extends Component {
  render() {
    return <Text>Hello, I am your cat!</Text>;
  }
}

export default Cat;

هذه إحدى الطرق العديدة لتصدير المكون الخاص بك، إذ يعمل هذا النوع من التصدير بصورةٍ جيدة مع المحرر Snack Player الذي يعمل على الإنترنت. لكنك قد تحتاج إلى استخدام طريقة مختلفة بناءً على بنية ملف تطبيقك. يمكنك الاطلاع على طرق الاستيراد والتصدير في لغة JavaScript.

لنلقِ نظرة على عبارة return وهي: <Text>Hello, I am your cat!</Text> التي نوعًا من الصياغة بلغة JavaScript التي تجعل كتابة العناصر مريحة، وهذه الصياغة هي JSX.

JSX

تستخدم React و React Native صياغة JSX، وهي صياغة تتيح لك كتابة عناصر داخل شيفرة JavaScript مثل: <Text>Hello, I am your cat!</Text> . يمكن استخدام المتغيرات ضمن JSX لأنها شيفرة JavaScript. يصرّح المثال التالي عن اسم القطة name ويضمّنه قوسين معقوصين ضمن الوسم <Text>.

import React from 'react';
import { Text } from 'react-native';

const Cat = () => {
  const name = "Maru";
  return (
    <Text>Hello, I am {name}!</Text>
  );
}

export default Cat;

سيعمل أي تعبير بلغة JavaScript موجود بين القوسين المعقوصين بما في ذلك استدعاءات الدوال كالاستدعاء {getFullName("Rum", "Tum", "Tugger")}:

import React from 'react';
import { Text } from 'react-native';

const getFullName = (firstName, secondName, thirdName) => {
  return firstName + " " + secondName + " " + thirdName;
}

const Cat = () => {
  return (
    <Text>
      Hello, I am {getFullName("Rum", "Tum", "Tugger")}!
    </Text>
  );
}

export default Cat;

يمكنك عدّ الأقواس المعقوصة كبوابة إلى جافاسكريبت ضمن JSX.

تُضمَّن JSX في مكتبة React، وبالتالي فلن تعمل بصورة صحيحة إن لم تضع الترويسة 'import React from 'react في أعلى الملف.

المكونات المخصَّصة Custom Components

تحدثنا سابقًا عن مكونات React Native الأساسية، إذ تتيح مكتبة React أن تتداخل هذه المكونات ضمن بعضها البعض لإنشاء مكونات جديدة. تقع هذه المكونات المتداخلة والقابلة لإعادة الاستخدام في صميم نموذج React.

يمكن وضع المكون Text والمكون TextInput داخل المكون View كما في المثال التالي، وتخرجها مكتبة React Native معًا:

import React from 'react';
import { Text, TextInput, View } from 'react-native';

const Cat = () => {
  return (
    <View>
      <Text>Hello, I am...</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: 'gray',
          borderWidth: 1
        }}
        defaultValue="Name me!"
      />
    </View>
  );
}

export default Cat;
ملاحظات المطور

في نظام Android: توضَع العروض views ضمن تخطيط LinearLayout أو FrameLayout أو RelativeLayout وما إلى ذلك من أجل تحديد طريقة ترتيب أبناء العرض view على الشاشة. يستخدم المكون View في React Native التخطيط باستخدام Flexbox من أجل ترتيب المكونات الأبناء. في الويب: إن كنت على دراية بتطوير الويب، فقد يذكّرك المكوّنان <View> و <Text> بلغة HTML. يمكنك عدّ هذين المكوّنين وسومًا لتطوير التطبيقات مثل الوسمين <div> و <p> .

يمكن إخراج المكون المخصَّص عدة مرات وبأماكن متعددة دون الحاجة إلى تكرار الشيفرة باستخدام <Cat> فقط:

import React from 'react';
import { Text, TextInput, View } from 'react-native';

const Cat = () => {
  return (
    <View>
      <Text>I am also a cat!</Text>
    </View>
  );
}

const Cafe = () => {
  return (
    <View>
      <Text>Welcome!</Text>
      <Cat />
      <Cat />
      <Cat />
    </View>
  );
}

export default Cafe;

يُدعَى أي مكوّنٍ يخرج مكونًا آخر بالمكوّن الأب parent component، فالمكوّن Cafe هو المكون الأب في مثالنا وكل مكون Cat هو مكون ابن child component. يمكنك وضع العدد الذي تريده من المكونات Cat ضمن المكون Cafe، ويخرج كل مكون <Cat> عنصرًا مختلفًا عن غيره، إذ يمكنك تخصيص هذا العنصر باستخدام props.

Props

كلمة Props هي اختصار للكلمة "properties" أي خصائص، وعملها مساعدتك على تخصيص مكوّنات React. تمرر كل <Cat> في المثال التالي اسمًا مختلفًا name للمكون Cat لإخراجه:

import React from 'react';
import { Text, View } from 'react-native';

const Cat = (props) => {
  return (
    <View>
      <Text>Hello, I am {props.name}!</Text>
    </View>
  );
}

const Cafe = () => {
  return (
    <View>
      <Cat name="Maru" />
      <Cat name="Jellylorum" />
      <Cat name="Spot" />
    </View>
  );
}

export default Cafe;

يمكن تخصيص معظم مكونات React Native الأساسية باستخدام props أيضًا، كأن تمرر خاصيةً prop تدعى source عند استخدام المكون Image لتحديد الصورة المعروضة على سبيل المثال:

import React from 'react';
import { Text, View, Image } from 'react-native';

const CatApp = () => {
  return (
    <View>
      <Image
        source={{uri: "https://reactnative.dev/docs/assets/p_cat1.png"}}
        style={{width: 200, height: 200}}
      />
      <Text>Hello, I am your cat!</Text>
    </View>
  );
}

export default CatApp;

للمكون Image خصائص متعددة مختلفة بما في ذلك style التي تقبل كائن تصميم في لغة جافاسكريبت وأزواج قيمة-خاصية (property-value) المتعلقة بالتخطيط.

لاحظ وجود الأقواس المعقوصة المضاعفة {{ }} التي تحيط بخاصيات طول وعرض style. يُشار إلى قيم JavaScript بقوسين معقوصين {} فقط ضمن JSX، وهذا مفيد عند تمرير شيءٍ آخر غير السلاسل string على أنها خصائص props، كتمرير مصفوفة array أو عدد: </ Cat food={["fish", "kibble"]} age={2}>. يُشار أيضًا إلى الكائنات المكتوبة بلغة جافاسكريبت باستخدام قوسين معقوصين: {width: 200, height: 200}، لذلك يجب تغليف كائن جافاسكريبت بقوسين معقوصين آخرين عند تمريره في JSX كما يلي: {{width: 200, height: 200}}.

يمكنك بناء أشياء متعددة باستخدام props والمكونات الأساسية Text و Image و View، ولكنك ستحتاج الحالة state لبناء شيء تفاعلي.

الحالة State

يمكنك عدّ props كوسطاء تستخدمها لضبط كيفية إخراج المكونات، ولكن الحالة state شبيهة بتخزين بيانات المكون الشخصية، وتُعَد مفيدة لمعالجة البيانات التي تتغير بمرور الوقت أو التي تنشأ من تفاعل المستخدم، أي أن الحالة تعطي ذاكرةً لمكوناتك.

يمكن بالحالة العامة استخدام props لضبط مكون عند إخراجه، واستخدام الحالة لتتبّع بيانات مكون تتوقّع تغيّرها بمرور الوقت.

يحدث المثال التالي في مقهىً للقطط حيث تنتظر قطتان جائعتان إطعامهما. نتوقع تغير جوع هاتين القطتين بمرور الوقت بعكس الاسم الذي لن تغير أبدًا، وبالتالي سيُخزَّن هذا الجوع كحالة. يمكنك الضغط على زرَي هاتين القطتين لإطعامهما، وبالتالي تتغير حالتهما.

مكون الدالة Function Component

يمكن إضافة حالة لمكونٍ ما من خلال استدعاء خطّاف React الذي يُسمَّى useState. الخطاف Hook هو نوعٌ من الدوال التي تسمح بالربط بميزات مكتبة React مثل الخطاف useState الذي يتيح لك إضافة حالة مكونات الدالة:

import React, { useState } from "react";
import { Button, Text, View } from "react-native";

const Cat = (props) => {
  const [isHungry, setIsHungry] = useState(true);

  return (
    <View>
      <Text>
        I am {props.name}, and I am {isHungry ? "hungry" : "full"}!
      </Text>
      <Button
        onPress={() => {
          setIsHungry(false);
        }}
        disabled={!isHungry}
        title={isHungry ? "Pour me some milk, please!" : "Thank you!"}
      />
    </View>
  );
}

const Cafe = () => {
  return (
    <>
      <Cat name="Munkustrap" />
      <Cat name="Spot" />
    </>
  );
}

export default Cafe;

مكون الصنف Class Component

يختلف نهج مكونات الصنف القديمة قليلًا عندما يتعلق الأمر بالحالة:

import React, { Component } from "react";
import { Button, Text, View } from "react-native";

class Cat extends Component {
  state = { isHungry: true };

  render() {
    return (
      <View>
        <Text>
          I am {this.props.name}, and I am
          {this.state.isHungry ? " hungry" : " full"}!
        </Text>
        <Button
          onPress={() => {
            this.setState({ isHungry: false });
          }}
          disabled={!this.state.isHungry}
          title={
            this.state.isHungry ? "Pour me some milk, please!" : "Thank you!"
          }
        />
      </View>
    );
  }
}

class Cafe extends Component {
  render() {
    return (
      <>
        <Cat name="Munkustrap" />
        <Cat name="Spot" />
      </>
    );
  }
}

export default Cafe;

يجب استيراد الصنف Component من مكتبة React كما هو الحال دائمًا مع مكونات الصنف:

import React, { Component } from 'react';

وتُخزَّن الحالة ضمن كائن حالة في مكونات الصنف:

export class Cat extends Component {
  state = { isHungry: true };
  //..
}

يمكن الوصول إلى props باستخدام العبارة this.props ، وكذلك يمكن الوصول إلى كائن الحالة ضمن المكون باستخدام العبارة this.state:

<Text>
  I am {this.props.name}, and I am
  {this.state.isHungry ? ' hungry' : ' full'}!
</Text>

وتُضبَط القيم الفردية في كائن الحالة من خلال تمرير كائن الزوج المفتاح-القيمة للحالة وتمرير قيمته الجديدة للدالة ()this.setState:

<Button
  onPress={() => {
    this.setState({ isHungry: false });
  }}
  // ..
/>

لا تغير حالة المكون الحاص بك مباشرةً من خلال إسناد قيمة جديدة إليها باستخدام العبارة this.state.hunger = false. يسمح استدعاء الدالة ()this.setState لمكتبة React تتبّعَ التغيرات التي أجريت على الحالة التي تنبّه إعادة الإخراج rerendering. يمكن أن يؤدي إعداد الحالة مباشرةً إلى تعطيل تفاعل تطبيقك.

تُضبَط قيمة الخاصية disabled الخاصة بالمكون Button وتتغير قيمة الخاصية title أيضًا، عندما تكون this.state.isHungry قيمتها false:

<Button
  // ..
  disabled={!this.state.isHungry}
  title={
    this.state.isHungry
      ? 'Pour me some milk, please!'
      : 'Thank you!'
  }
/>

أخيرًا، ضع القطط ضمن مكون المقهى Cafe كما يلي:

class Cafe extends Component {
  render() {
    return (
      <>
        <Cat name="Munkustrap" />
        <Cat name="Spot" />
      </>
    );
  }
}

export default Cafe;

تُدعَى <> و </> بالأجزاء fragments. يجب أن تُغلَّف عناصر JSX المتجاورة بوسم يحيط بها، إذ تتيح لك هذه الأجزاء فعل ذلك دون أن تتداخل عنصر تغليف إضافي غير ضروري مثل View.