طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 251 · برمجة الأجهزة الذكية
الدرس 11 · الوحدة 5: تطوير تطبيقات باستخدام React Native

جلب البيانات وعرضها في قائمة حيّة

إحضار البيانات من الشبكة وعرضها بأمان. ⏱ نحو 40 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تفهم أن البيانات تأتي لاحقًا بثلاث حالات.
  • تجلب البيانات بـ useEffect وتدير حالة التحميل.
  • تعالج الخطأ بـ catch وتمنع التحديث بعد الإزالة.

١البيانات تأتي لاحقًا

تطبيقٌ حقيقيّ يجلب بياناته من خادم عبر الشبكة. والشبكة غير فورية: يمرّ التطبيق بثلاث حالات — تحميل، ثم نجاح (بيانات) أو خطأ. نعرض لكلٍّ واجهةً مناسبة:

الحالةما نعرضه
تحميلمؤشّر «جارٍ التحميل…»
نجاحالبيانات في قائمة
خطأرسالة ونعرض زرّ إعادة

٢النمط: useEffect + حالة تحميل

نجلب البيانات مرّةً عند ظهور المكوّن (useEffect بمصفوفةٍ فارغة)، ونحفظ حالتَي التحميل والبيانات:

import { useState, useEffect } from 'react';import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native'; // محاكاة خادم: يردّ بعد نصف ثانيةfunction fetchProducts() {  return new Promise((resolve) => {    setTimeout(() => resolve([      { id: '1', name: 'قهوة', price: 20 },      { id: '2', name: 'شاي', price: 12 },      { id: '3', name: 'عصير', price: 15 },    ]), 500);  });} export default function App() {  const [loading, setLoading] = useState(true);  const [items, setItems] = useState([]);   useEffect(() => {    fetchProducts().then((data) => {      setItems(data);      setLoading(false);    });  }, []);   if (loading) return <ActivityIndicator style={{ margin: 30 }} color="#E8820C" />;   return (    <FlatList      style={{ padding: 10 }}      data={items}      keyExtractor={(it) => it.id}      renderItem={({ item }) => (        <View style={styles.row}>          <Text>{item.name}</Text>          <Text style={styles.p}>{item.price} ر.س</Text>        </View>      )}    />  );} const styles = StyleSheet.create({  row: { flexDirection: 'row', justifyContent: 'space-between', padding: 12, borderBottomWidth: 1, borderColor: '#eee' },  p: { color: '#E8820C', fontWeight: 'bold' },});

لاحظ المؤشّر أولًا ثم ظهور القائمة. ActivityIndicator مكوّنٌ جاهز لحالة التحميل.

٣معالجة الخطأ

الشبكة قد تفشل. نلتقط الخطأ ونعرض رسالةً بدل انهيار التطبيق:

useEffect(() => {  let alive = true;  fetchProducts()    .then((data) => { if (alive) { setItems(data); setLoading(false); } })    .catch(() => { if (alive) { setError(true); setLoading(false); } });  return () => { alive = false; };   // لا تحدّث مكوّنًا أُزيل}, []);

المتغيّر alive يمنع تحديث الحالة بعد إزالة المكوّن (خطأ شائع). وcatch يحوّلنا لحالة الخطأ.

توقّع وتحقّق

ما الحالات الثلاث لجلب البيانات؟

متى نجلب البيانات عادةً؟

مكوّن مؤشّر التحميل الجاهز:

لمعالجة فشل الشبكة نستخدم:

الخلاصة

تحدٍّ برمجي: جلب أسماء

متقدم

اجلب قائمةً من مصدرٍ محاكى واعرض عددها.

المطلوب:
  • دالّة محاكاة تُرجع وعدًا بمصفوفة أسماء (3 على الأقل).
  • اجلبها في useEffect مرّةً، واحفظها في حالة.
  • <Text testID="count"> يعرض عددها بعد الجلب.
👀 اعرض الناتج المطلوب (وجرّبه)
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء في Console
  • العدّاد يظهر 3 بعد الجلب
  • استُخدم useEffect
  • جُلبت البيانات بوعد then

💡 تلميح 1
اجلب في useEffect(() => {{ fetchNames().then(setNames); }}, []).
💡 تلميح 2
العدّاد: {names.length}.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

import { useState, useEffect } from 'react';import { View, Text, StyleSheet } from 'react-native'; function fetchNames() {  return Promise.resolve(['سعود', 'نورة', 'خالد']);} export default function App() {  const [names, setNames] = useState([]);  useEffect(() => {    fetchNames().then(setNames);  }, []);  return (    <View style={{ padding: 20 }}>      <Text testID="count" style={styles.c}>العدد: {names.length}</Text>    </View>  );} const styles = StyleSheet.create({  c: { fontSize: 22, fontWeight: 'bold', color: '#E8820C' },});
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس