React📅 2026-10-16⏱ 9 دقائق قراءة⚛️ مقال 7 من 10

القوائم والشروط في React — دليل شامل 2026

دليل عملي مفصل للقوائم والشروط في React — map, filter, key، والتصيير الشرطي، مع تمارين وحلول

في المقال السابق، تعلمت useEffect وإدارة التأثيرات الجانبية. الآن سنتعلم القوائم (Lists) و الشروط (Conditionals) — وهي الطريقة التي نعرض بها البيانات ديناميكياً في React.

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

عرض القوائم

1. الطريقة الأساسية — map

function FruitList() {
  const fruits = ["تفاح", "موز", "برتقال"];

  return (
    <ul>
      {fruits.map((fruit) => (
        <li key={fruit}>{fruit}</li>
      ))}
    </ul>
  );
}

شرح:

  • map: تُحوّل كل عنصر في المصفوفة إلى JSX.
  • key: معرّف فريد لكل عنصر (مهم للأداء).

2. قائمة كائنات

interface User {
  id: number;
  name: string;
  email: string;
}

function UserList() {
  const users: User[] = [
    { id: 1, name: "أحمد", email: "[email protected]" },
    { id: 2, name: "محمد", email: "[email protected]" },
    { id: 3, name: "علي", email: "[email protected]" },
  ];

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>
          <strong>{user.name}</strong> - {user.email}
        </li>
      ))}
    </ul>
  );
}

3. استخدام مكوّن منفصل

interface UserProps {
  user: User;
}

function UserItem({ user }: UserProps) {
  return (
    <li>
      <strong>{user.name}</strong> - {user.email}
    </li>
  );
}

function UserList() {
  const users: User[] = [...];

  return (
    <ul>
      {users.map((user) => (
        <UserItem key={user.id} user={user} />
      ))}
    </ul>
  );
}

أهمية key

key هو معرّف فريد لكل عنصر في القائمة.

لماذا key مهم؟

  • الأداء: React يستخدمه لمعرفة العناصر التي تغيرت.
  • الحالة: يحافظ على state العناصر.
  • التحذيرات: بدون key، React يعطي تحذيراً.

❌ طرق خاطئة:

// ❌ بدون key:
{items.map((item) => <li>{item}</li>)}

// ❌ استخدام index (خطر):
{items.map((item, index) => <li key={index}>{item}</li>)}

⚠️ لماذا index خطير؟

  • عند إضافة/حذف عنصر، تتغير الـ indices.
  • React قد يعيد استخدام العناصر بشكل خاطئ.
  • يفقد state العنصر.

✅ الطريقة الصحيحة:

// ✅ باستخدام id فريد:
{items.map((item) => <li key={item.id}>{item.name}</li>)}

// ✅ باستخدام قيمة فريدة:
{fruits.map((fruit) => <li key={fruit}>{fruit}</li>)}

الشروط في JSX

1. if خارج JSX

function Greeting({ isLoggedIn }: { isLoggedIn: boolean }) {
  if (isLoggedIn) {
    return <h1>مرحباً بك!</h1>;
  }
  return <h1>سجّل الدخول</h1>;
}

2. Ternary Operator (? :)

function Greeting({ isLoggedIn }: { isLoggedIn: boolean }) {
  return (
    <h1>{isLoggedIn ? "مرحباً بك!" : "سجّل الدخول"}</h1>
  );
}

الاستخدام: خياران فقط.

3. && — العرض الشرطي

function Inbox({ messages }: { messages: string[] }) {
  return (
    <div>
      <h1>صندوق الوارد</h1>
      {messages.length > 0 && (
        <p>لديك {messages.length} رسالة</p>
      )}
      {messages.length === 0 && <p>لا توجد رسائل</p>}
    </div>
  );
}

⚠️ تحذير: إذا كانت القيمة 0، ستُعرض 0 في JSX!

// ❌ خطأ (يعرض "0" إذا كان length === 0):
{messages.length && <p>...</p>}

// ✅ صحيح:
{messages.length > 0 && <p>...</p>}

4. if-else if-else — حالات متعددة

function StatusBadge({ status }: { status: "pending" | "approved" | "rejected" }) {
  if (status === "pending") {
    return <span className="yellow">⏳ قيد المراجعة</span>;
  }
  if (status === "approved") {
    return <span className="green">✅ مقبول</span>;
  }
  return <span className="red">❌ مرفوض</span>;
}

5. switch — حالات كثيرة

function Icon({ type }: { type: string }) {
  switch (type) {
    case "user":
      return <span>👤</span>;
    case "email":
      return <span>📧</span>;
    case "phone":
      return <span>📱</span>;
    default:
      return <span>❓</span>;
  }
}

التصيير المتقدم

1. تصفية القائمة

function ProductList({ products, showInStock }: { products: Product[]; showInStock: boolean }) {
  const filtered = showInStock
    ? products.filter((p) => p.inStock)
    : products;

  return (
    <ul>
      {filtered.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  );
}

2. ترتيب القائمة

const sorted = [...products].sort((a, b) => a.price - b.price);

3. البحث

const [query, setQuery] = useState("");
const filtered = products.filter((p) =>
  p.name.toLowerCase().includes(query.toLowerCase())
);

4. تجميع القائمة

const grouped = products.reduce<Record<string, Product[]>>((acc, p) => {
  const category = p.category;
  if (!acc[category]) acc[category] = [];
  acc[category].push(p);
  return acc;
}, {});

مثال عملي: قائمة مهام كاملة

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

function TodoApp() {
  const [todos, setTodos] = useState<Todo[]>([
    { id: 1, text: "تعلم React", completed: true },
    { id: 2, text: "بناء مشروع", completed: false },
    { id: 3, text: "نشر الموقع", completed: false },
  ]);
  const [filter, setFilter] = useState<"all" | "active" | "completed">("all");

  const filteredTodos = todos.filter((todo) => {
    if (filter === "active") return !todo.completed;
    if (filter === "completed") return todo.completed;
    return true;
  });

  return (
    <div className="todo-app">
      <h1>📝 قائمة المهام</h1>

      <div className="filters">
        <button onClick={() => setFilter("all")}>الكل</button>
        <button onClick={() => setFilter("active")}>النشطة</button>
        <button onClick={() => setFilter("completed")}>المكتملة</button>
      </div>

      {filteredTodos.length === 0 ? (
        <p className="empty">لا توجد مهام</p>
      ) : (
        <ul>
          {filteredTodos.map((todo) => (
            <li key={todo.id} className={todo.completed ? "done" : ""}>
              <input
                type="checkbox"
                checked={todo.completed}
                onChange={() =>
                  setTodos(
                    todos.map((t) =>
                      t.id === todo.id ? { ...t, completed: !t.completed } : t
                    )
                  )
                }
              />
              <span>{todo.text}</span>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

مثال عملي: قائمة منتجات

interface Product {
  id: number;
  name: string;
  price: number;
  image: string;
  inStock: boolean;
}

function ProductGrid() {
  const products: Product[] = [
    { id: 1, name: "لابتوب", price: 5000, image: "...", inStock: true },
    { id: 2, name: "هاتف", price: 2000, image: "...", inStock: true },
    { id: 3, name: "تابلت", price: 1500, image: "...", inStock: false },
  ];

  return (
    <div className="grid">
      {products.map((product) => (
        <div key={product.id} className="product-card">
          <img src={product.image} alt={product.name} />
          <h3>{product.name}</h3>
          <p>{product.price} $</p>
          {product.inStock ? (
            <span className="in-stock">✅ متوفر</span>
          ) : (
            <span className="out-of-stock">❌ غير متوفر</span>
          )}
        </div>
      ))}
    </div>
  );
}

عرض البيانات الشرطية المتقدمة

1. حالات API (Loading/Error/Success)

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string[] }
  | { status: "error"; message: string };

function DataView() {
  const [state, setState] = useState<State>({ status: "idle" });

  if (state.status === "loading") return <p>جاري التحميل...</p>;
  if (state.status === "error") return <p>خطأ: {state.message}</p>;
  if (state.status === "success") {
    return (
      <ul>
        {state.data.map((item, i) => (
          <li key={i}>{item}</li>
        ))}
      </ul>
    );
  }
  return <button onClick={() => setState({ status: "loading" })}>ابدأ</button>;
}

2. عرض شرطي متداخل

function UserProfile({ user }: { user: User | null }) {
  if (!user) return <p>لم يتم تسجيل الدخول</p>;

  return (
    <div>
      <h2>{user.name}</h2>
      {user.isAdmin && <span className="badge">👑 مدير</span>}
      {user.posts.length > 0 ? (
        <ul>
          {user.posts.map((post) => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      ) : (
        <p>لا توجد مقالات</p>
      )}
    </div>
  );
}

تمارين عملية

تمرين 1: قائمة أسماء

اعرض مصفوفة أسماء في قائمة.

الحل:

function Names() {
  const names = ["أحمد", "محمد", "علي"];
  return <ul>{names.map((n) => <li key={n}>{n}</li>)}</ul>;
}

تمرين 2: قائمة أرقام مع شرط

اعرض الأرقام الزوجية فقط.

الحل:

function EvenNumbers() {
  const nums = [1, 2, 3, 4, 5, 6];
  const evens = nums.filter((n) => n % 2 === 0);
  return <ul>{evens.map((n) => <li key={n}>{n}</li>)}</ul>;
}

تمرين 3: عرض شرطي

اعرض "مرحباً" إذا كان isLoggedIn صحيحاً، وإلا "سجّل الدخول".

الحل:

function Greeting({ isLoggedIn }: { isLoggedIn: boolean }) {
  return <h1>{isLoggedIn ? "مرحباً" : "سجّل الدخول"}</h1>;
}

تمرين 4: قائمة مهام مع تصفية

اعرض المهام النشطة فقط.

الحل:

function ActiveTodos() {
  const todos = [
    { id: 1, text: "مهمة 1", done: true },
    { id: 2, text: "مهمة 2", done: false },
    { id: 3, text: "مهمة 3", done: false },
  ];
  const active = todos.filter((t) => !t.done);
  return <ul>{active.map((t) => <li key={t.id}>{t.text}</li>)}</ul>;
}

تمرين 5: حالة فارغة

اعرض "لا توجد بيانات" إذا كانت القائمة فارغة.

الحل:

function EmptyList({ items }: { items: string[] }) {
  if (items.length === 0) return <p>لا توجد بيانات</p>;
  return <ul>{items.map((i) => <li key={i}>{i}</li>)}</ul>;
}

تمرين 6: بحث في القائمة

اعرض فقط المنتجات التي تحتوي على نص البحث.

الحل:

function SearchProducts() {
  const [query, setQuery] = useState("");
  const products = ["لابتوب", "هاتف", "تابلت", "سماعات"];
  const filtered = products.filter((p) =>
    p.toLowerCase().includes(query.toLowerCase())
  );
  return (
    <div>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <ul>{filtered.map((p) => <li key={p}>{p}</li>)}</ul>
    </div>
  );
}

تمرين 7: ترتيب القائمة

اعرض الأرقام مرتبة تصاعدياً.

الحل:

function SortedNumbers() {
  const nums = [5, 2, 8, 1, 9, 3];
  const sorted = [...nums].sort((a, b) => a - b);
  return <ul>{sorted.map((n) => <li key={n}>{n}</li>)}</ul>;
}

تمرين 8: جدول مستخدمين

اعرض جدول مستخدمين مع حالاتهم.

الحل:

interface User {
  id: number;
  name: string;
  active: boolean;
}

function UsersTable() {
  const users: User[] = [
    { id: 1, name: "أحمد", active: true },
    { id: 2, name: "محمد", active: false },
    { id: 3, name: "علي", active: true },
  ];

  return (
    <table>
      <thead>
        <tr>
          <th>الاسم</th>
          <th>الحالة</th>
        </tr>
      </thead>
      <tbody>
        {users.map((user) => (
          <tr key={user.id}>
            <td>{user.name}</td>
            <td>{user.active ? "✅ نشط" : "❌ غير نشط"}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

حل المشاكل الشائعة

🔴 المشكلة 1: Warning: Each child in a list should have a unique "key" prop

السبب: عدم وجود key في القائمة.

الحل: أضف key فريد.

🔴 المشكلة 2: Objects are not valid as a React child

السبب: عرض كائن مباشرة.

الحل: اعرض خاصية من الكائن.

🔴 المشكلة 3: عرض 0 بدلاً من لا شيء

السبب: استخدام && مع رقم.

الحل:

// ❌
{items.length && <p>...</p>}

// ✅
{items.length > 0 && <p>...</p>}

🔴 المشكلة 4: Cannot read property 'map' of undefined

السبب: القيمة غير معرّفة.

الحل:

{items?.map(...) || <p>لا توجد بيانات</p>}

جدول طرق القوائم

الطريقةالوظيفة
mapتحويل كل عنصر
filterتصفية العناصر
sortترتيب
reduceتجميع
sliceجزء من القائمة
findإيجاد عنصر

قائمة تحقق نهائية

المهمةالحالة
عرض القوائم باستخدام map⬜
فهم أهمية key⬜
الشروط باستخدام ? :⬜
الشروط باستخدام &&⬜
تصفية وترتيب القوائم⬜
الحالات المعقدة (Loading/Error)⬜
حل التمارين الثمانية⬜

ماذا بعد هذا المقال؟

الآن بعد أن أتقنت القوائم والشروط، أنت جاهز للمقال التالي:

  1. React Router — التنقل بين الصفحات.
  2. Context API — إدارة الحالة العامة.
  3. مشروع متكامل — تطبيق كامل.

الخلاصة

في هذا المقال، تعلمت:

  • ✅ عرض القوائم باستخدام map.
  • ✅ أهمية key ولماذا index خطر.
  • ✅ الشروط في JSX (? :, &&, if).
  • ✅ تصفية وترتيب القوائم.
  • ✅ الحالات المعقدة (Loading/Error/Success).
  • ✅ حل 8 تمارين عملية.

تذكر: القوائم والشروط هي أساس كل تطبيق ديناميكي. أتقنها جيداً.

هل أتقنت القوائم والشروط؟ شاركنا في التعليقات!

📚 مقالات ذات صلة

React

مشروع React متكامل — تطبيق متجر إلكتروني 2026

مشروع عملي شامل لبناء تطبيق متجر إلكتروني بـ React و TypeScript — مع السلة، البحث، التصفية، والحفظ التلقائي

React

Context API في React — إدارة الحالة العامة 2026

دليل عملي مفصل لـ Context API في React — إنشاء Context، Provider، useContext، مع تمارين وحلول

React

React Router — التنقل بين الصفحات في React 2026

دليل عملي مفصل لـ React Router — التنقل، المسارات، الروابط، والمعاملات، مع تمارين وحلول