أساسيات إطار العمل React Native
إطار العمل React Native يشبه React، لكنه يستخدم مكونات أصيلة بدلًا من مكونات الويب كعناصر أساسية. يجب أن تفهم أولًا بعضًا من مفاهيم React الأساسية، مثل JSX والمكوّنات والحالة state
والخاصيات props
، لفهم البنية الأساسية لتطبيق React Native. إذا كانت لديك خبرة سابقة مع React، فلا تزال بحاجة إلى معرفة بعض الأمور الخاصة بإطار عمل React Native، كالمكونات الأصيلة native components مثلًا. هذا الدليل التطبيقي موجّه إلى جميع الفئات، سواء كانت لديك تجربة مع React أم لا.
المثال الأول: مرحبًا بالعالم Hello World
سنبدأ أولًا ببناء تطبيقٍ الغرض الوحيد منه هو عرض جملة "مرحبًا بالعالم Hello World" كما يلي (تجربة حية):
import React from 'react';
import { Text, View } from 'react-native';
const HelloWorldApp = () => {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center"
}}>
<Text>Hello, world!</Text>
</View>
)
}
export default HelloWorldApp;
يمكنك تعديل عينة الشيفرة البرمجية مباشرة في محاكٍ على الويب مثل Expo، أو يمكنك لصقها في ملف App.js
لإنشاء تطبيق فعلي على جهازك المحلي.
شرح الشيفرة
- نحتاج أولًا إلى استيراد
React
لنتمكّن من استخدامJSX
، والتي ستُحوَّل بعد ذلك إلى المكونات الأصيلة لكل منصة. - استوردنا المكوّنين
Text
وView
منreact-native
في السطر الثاني من الشيفرة السابقة.
ثم ستجد الدالة HelloWorldApp
، وهي مكون دالة functional component، وتتصرف هذه الدالة بالطريقة نفسها في React للويب. تعيد هذه الدالة مكون View
مع بعض الأنماط والمكوّن Text
كابنٍ لها.
يسمح المكون Text
بتصيير render نص، بينما يصيّر المكوّن View
حاوية. طُبِّقت أنماط متعددة على هذه الحاوية، إذًا لنحلل عمل كل نمط منها.
النمط الأول هو flex: 1
، حيث ستحدّد الخاصية flex
كيف "تَملأ" عناصرك المساحةَ المتوفرة اعتمادًا على المحور الرئيسي main axis. بما أن لدينا حاوية واحدة فقط، لذلك ستشغَل هذه الحاوية كل المساحة المكون الأب المتاحة، وبما أنها المكون الوحيد في هذه الحالة، فستأخذ كل مساحة الشاشة المتاحة.
النمط التالي هو justifyContent: "center"
. يؤدي هذا النمط إلى محاذاة العناصر الأبناء للحاوية في مركز محور الحاوية الرئيسي. أخيرًا، لدينا النمط alignItems: "center"
، والذي يؤدي إلى محاذاة عناصر الحاوية في مركز محور الحاوية المتعامد مع المحور الرئيسي cross axis.
قد تبدو بعض الأجزاء في الشيفرة أعلاه مختلفة عن لغة JavaScript التي اعتدت عليها، لا تقلق، فهذه شيفرة JavaScript بنسختها ES2015 (التي تعرف كذلك بالرمز ES6)، وهي نسخة جديدة من JavaScript تُضيف مجموعة من التحسينات التي أصبحت الآن جزءًا من معيار JavaScript الرسمي، لكنّها غير مدعومة على جميع المتصفّحات، لذلك لا تُستخدَم عادةً في تطوير الويب. يدعم React Native النسخة ES2015 افتراضيًّا، لذلك يُمكنك استخدام الميّزات الجديدة من JavaScript دون القلق بشأن التوافق. الجمل from
و import
و class
وextends
في المثال أعلاه كلها ميزات ES2015. إن لم تعرف ميّزات النسخة الجديدة من JavaScript، فربّما يُمكنك تعلّمها فقط من خلال قراءة شيفراتٍ برمجيّةٍ كالشيفرة السابقة، أو اطّلع على هذه السلسلة من الدروس، إضافة إلى أنّ توثيق JavaScript في الموسوعة يُغطّي ميّزات ES6 كذلك (استعن بمربّع البحث للوصول إلى صفحات معيّنة).
أما الشيء الآخر غير المعتاد في الشيفرة السابقة فهو الجزء التالي:
<View><Text>Hello world!</Text></View>
هذه شيفرة JSX وهي بنيةٌ برمجيّةٌ أو صياغة syntax لتضمين XML داخل شيفرة JavaScript. تَستخدم العديد من أطر العمل لغة قوالب templating language خاصة تسمح لك بتضمين شيفرة برمجيّة داخل لغة ترميز markup language. يحدث عكس ذلك في شيفرة React، إذ تتيح لك JSX كتابة لغة ترميز داخل شيفرة برمجيّة. الشيفرة مشابهة للغة HTML على الويب، باستثناء أنّ عناصر الويب مثل <div>
أو <span>
تُستبدَل بمكونات React. في هذه الحالة، <Text>
هو مكونٌ أساسي يُستخدَم لعرض مقطعٍ نصيٍّ، أمّا View
فهو مكوّن يشبه <div>
أو <span>
.
المكونات Components
تُعرِّف الشيفرة أعلاه مكوّنًا جديدًا باسم HelloWorldApp
. ستُنشئ العديد من المكونات الجديدة أثناء تطويرك للتطبيقات بإطار عمل React Native. كلّ ما تراه على الشاشة هو مكوّنٌ من هذه المكونات.
الخاصيات Props
يمكن تخصيص معظم المكونات عند إنشائها باستخدام معاملات مختلفة، حيث تسمّى معاملات الإنشاء هذه بالخاصيات props.
يمكن لمكوناتك الخاصة أيضًا استخدام الخاصيات props
، إذ يتيح لك ذلك إنشاء مكون واحد يمكن استخدامه في أماكن مختلفة من تطبيقك، ومع خاصيات مختلفة قليلًا في مكانٍ ما مختلف عن الآخر. يُشار إلى هذه الخاصيات بالشكل props.YOUR_PROP_NAME
في مكونات الدالة أو بالشكل this.props.YOUR_PROP_NAME
في مكونات الصنف الخاصة بك. اطّلع على المثال التالي (تجربة حية):
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
center: {
alignItems: 'center'
}
})
const Greeting = (props) => {
return (
<View style={styles.center}>
<Text>Hello {props.name}!</Text>
</View>
);
}
const LotsOfGreetings = () => {
return (
<View style={[styles.center, {top: 50}]}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
export default LotsOfGreetings;
يسمح استخدام الاسم name
كخاصية بتخصيص المكون Greeting
، لنتمكّن من إعادة استخدام هذا المكون لكل التحيات greetings. يستخدم هذا المثال أيضًا المكوّن Greeting
في JSX، وهذا ما يجعل React رائعةً للغاية.
الشيء الجديد الآخر هو المكون View
الذي يُعَد مفيدًا كحاوية للمكونات الأخرى بهدف التحكم في النمط والتخطيط.
يمكنك إنشاء مجموعة متنوعة من الشاشات الثابتة باستخدام الخاصيات props
ومكونات Text
و Image
و View
الأساسية، لكن يجب أن تعرف المزيد حول الحالة State لمعرفة كيفية تغيير تطبيقك بمرور الوقت.
الحالة State
تسمح الحالة state
لمكونات React بتغيير مخرجاتها بمرور الوقت استجابةً لإجراءات المستخدم واستجابات الشبكة وأي شيء آخر، بخلاف الخاصيات التي تكون قابلة للقراءة فقط ولا يجب تعديلها.
الفرق بين الحالة والخاصيات في React
الخاصيات في مكوِّن React هي المتغيرات التي نمررها من مكوّن أب إلى مكوّن ابن. أما الحالة فهي أيضًا متغيرات لكنها لا تُمرَّر كمعاملات حيث يهيّئها ويديرها المكوّن داخليًا.
هل توجد اختلافات بين React و React Native في التعامل مع الحالة؟
إليك مثال ReactJS لعدّاد Counter باستخدام الخطّافات Hooks:
import React, { useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
return (
<div className="container">
<p>You clicked {count} times</p>
<button
onClick={() => setCount(count + 1)}>
Click me!
</button>
</div>
);
};
// CSS
.container {
display: flex;
justify-content: center;
align-items: center;
}
انظر أيضًا مثال React Native لعّداد Counter باستخدام الخطّافات Hooks:
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const App = () => {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Text>You clicked {count} times</Text>
<Button
onPress={() => setCount(count + 1)}
title="Click me!"
/>
</View>
);
};
// React Native أنماط
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
لا يوجد فرق في التعامل مع الحالة بين React و React Native كما هو موضح أعلاه. يمكنك استخدام حالة المكونات الخاصة بك في كل من مكونات الدالة ومكونات الصنف باستخدام الخطّافات hooks. سنعرض في المثال التالي مثال العدّاد counter نفسه ولكن باستخدام الأصناف classes (تجربة حية):
import React, { Component } from 'react'
import {
StyleSheet,
TouchableOpacity,
Text,
View,
} from 'react-native'
class App extends Component {
state = {
count: 0
}
onPress = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={this.onPress}
>
<Text>Click me</Text>
</TouchableOpacity>
<View>
<Text>
You clicked { this.state.count } times
</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
marginBottom: 10
}
})
export default App;