التنقّل بين الشاشات
إدارة الشاشات المتعدّدة: الحالة تقرّر الظاهر. ⏱ نحو 40 دقيقة.
- تفهم أن التنقّل سؤالٌ تجيب عنه الحالة.
- تحاكي مكدّسًا (دخول/رجوع) وتبويباتٍ سفلية.
- تعرف دور
React Navigationعلى الجهاز.
١التطبيق شاشاتٌ متعدّدة
تطبيقٌ حقيقيّ ليس شاشةً واحدة: قائمةٌ ثم تفاصيل، تبويباتٌ سفلية، رجوع. إدارة «أيّ شاشةٍ ظاهرة الآن» اسمها التنقّل Navigation.
على الجهاز نستخدم مكتبة React Navigation (مكدّس Stack وتبويبات Tabs). لفهم الفكرة أولًا، نحاكي التنقّل بأبسط أدواتنا: الحالة. الشاشة الظاهرة مجرّد قيمةٍ في useState:
٢محاكاة مكدّس بسيط
حالةٌ تحمل اسم الشاشة الحالية، ودوالّ تغيّرها. هذا «مكدّسٌ» مبسّط: قائمة ← تفاصيل ← رجوع:
import { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; function Home({ go }) { return ( <View style={styles.screen}> <Text style={styles.h}>🏠 الرئيسية</Text> <Pressable style={styles.btn} onPress={() => go('details')}> <Text style={styles.bt}>افتح التفاصيل ←</Text> </Pressable> </View> );} function Details({ go }) { return ( <View style={styles.screen}> <Text style={styles.h}>📄 التفاصيل</Text> <Pressable style={styles.btn} onPress={() => go('home')}> <Text style={styles.bt}>→ رجوع</Text> </Pressable> </View> );} export default function App() { const [screen, setScreen] = useState('home'); return screen === 'home' ? <Home go={setScreen} /> : <Details go={setScreen} />;} const styles = StyleSheet.create({ screen: { padding: 24, alignItems: 'center', gap: 14 }, h: { fontSize: 24, fontWeight: 'bold' }, btn: { backgroundColor: '#E8820C', paddingVertical: 10, paddingHorizontal: 18, borderRadius: 10 }, bt: { color: 'white', fontSize: 16 },});
نمرّر دالّة التنقّل go كـ prop. كل شاشةٍ مكوّن، والحالة تقرّر الظاهر.
٣تبويباتٌ سفلية
نمطٌ شائع: شريط تبويباتٍ أسفل الشاشة. نحاكيه بالحالة أيضًا:
import { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; const TABS = [ { key: 'home', label: '🏠 الرئيسية' }, { key: 'cart', label: '🛒 السلّة' }, { key: 'me', label: '👤 حسابي' },]; export default function App() { const [tab, setTab] = useState('home'); const current = TABS.find(t => t.key === tab); return ( <View style={{ flex: 1, minHeight: 240 }}> <View style={styles.body}> <Text style={styles.big}>{current.label}</Text> </View> <View style={styles.tabbar}> {TABS.map(t => ( <Pressable key={t.key} style={styles.tab} onPress={() => setTab(t.key)}> <Text style={[styles.tt, tab === t.key && styles.active]}>{t.label}</Text> </Pressable> ))} </View> </View> );} const styles = StyleSheet.create({ body: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 }, big: { fontSize: 22, fontWeight: 'bold' }, tabbar: { flexDirection: 'row', borderTopWidth: 1, borderColor: '#eee' }, tab: { flex: 1, padding: 12, alignItems: 'center' }, tt: { color: '#888' }, active: { color: '#E8820C', fontWeight: 'bold' },});
كل تبويبٍ يغيّر الحالة، والمحتوى يتبعها. على الجهاز تفعل React Navigation هذا مع انتقالاتٍ جاهزة.
توقّع وتحقّق
التنقّل في جوهره سؤال:
المكتبة الشائعة للتنقّل على الجهاز:
كيف نحاكي الشاشة الحالية هنا؟
نمط «دخول ثم رجوع» اسمه:
الخلاصة
- التنقّل = «أيّ شاشةٍ أعرض؟»، تجيب عنه الحالة.
- المكدّس: دخول ثم رجوع؛ التبويبات: تنقّلٌ أفقيّ بين أقسام.
- على الجهاز نستخدم
React Navigation، لكن المبدأ هو الحالة.
تحدٍّ برمجي: تبديل شاشتين
متوسططبّق تنقّلًا بين شاشتين بالحالة.
- حالة
screenتبدأ بـ «one». - زرٌّ يبدّل بين «one» و«two».
<Text testID="title">يعرض «الشاشة الأولى» أو «الشاشة الثانية» حسب الحالة.
👀 اعرض الناتج المطلوب (وجرّبه)
- الكود يعمل بلا أخطاء في Console
- يبدأ بالشاشة الأولى
- بعد اللمس يصبح الثانية
- استُخدم useState
💡 تلميح 1
💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
import { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; export default function App() { const [screen, setScreen] = useState('one'); const title = screen === 'one' ? 'الشاشة الأولى' : 'الشاشة الثانية'; return ( <View style={{ padding: 20, gap: 12 }}> <Text testID="title" style={styles.h}>{title}</Text> <Pressable style={styles.btn} onPress={() => setScreen(screen === 'one' ? 'two' : 'one')}> <Text style={styles.bt}>تبديل</Text> </Pressable> </View> );} const styles = StyleSheet.create({ h: { fontSize: 22, fontWeight: 'bold', color: '#E8820C' }, btn: { backgroundColor: '#E8820C', padding: 12, borderRadius: 10, alignItems: 'center' }, bt: { color: 'white' },});