تخطَّ إلى المحتوى

⚛️ شرح React

الحالة (State) و useState

الدرس 4 من 32· ⏱ 2 دقائق قراءة· 🗓 آخر تحديث: ١٦ أكتوبر ٢٠٢٦

ما هي الحالة (State)؟

State بيانات تخصّ المكوّن ويمكن أن تتغيّر مع الوقت (مثل عدّاد أو نص حقل إدخال). عند تغيّر الحالة، تُعيد React رسم المكوّن تلقائيًا.

useState

نستخدم الخطّاف useState لتعريف حالة:

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>العدّ: {count}</p>
      <button onClick={() => setCount(count + 1)}>زيادة</button>
    </div>
  );
}

شرح السطر const [count, setCount] = useState(0):

  • count = القيمة الحالية (تبدأ بـ 0).
  • setCount = الدالة الوحيدة المسموح بها لتغيير القيمة.
  • useState(0) = القيمة الابتدائية.

القاعدة الذهبية

⚠️ لا تعدّل الحالة مباشرة! استخدم دائمًا دالة التحديث.

// ❌ خطأ — لن تتحدّث الواجهة
count = count + 1;

// ✅ صحيح
setCount(count + 1);

التحديث بناءً على القيمة السابقة

عند الاعتماد على القيمة الحالية، مرّر دالة:

setCount((prev) => prev + 1);

لماذا يهم هذا؟ count داخل الدالة هي لقطة من العرض الحالي، لا تتغيّر حتى العرض التالي. لذلك:

function handleClick() {
  setCount(count + 1);   // count = 0 → يطلب 1
  setCount(count + 1);   // count ما زالت 0 → يطلب 1 مرة أخرى
}
// النتيجة: 1 لا 2

function handleClickFixed() {
  setCount((prev) => prev + 1);   // 0 → 1
  setCount((prev) => prev + 1);   // 1 → 2
}
// النتيجة: 2

الكائنات والمصفوفات: أنشئ نسخة جديدة

React يقارن القيمة الجديدة بالقديمة بالمرجع. تعديل المصفوفة نفسها لا يغيّر مرجعها، فلا يرى React أي تغيير ولا يعيد العرض:

const [items, setItems] = useState(["أ"]);

// ❌ نفس المصفوفة بعد تعديلها — لن تتحدّث الواجهة
items.push("ب");
setItems(items);

// ✅ مصفوفة جديدة
setItems([...items, "ب"]);

// ✅ ونفس الفكرة مع الكائنات
const [user, setUser] = useState({ name: "سارة", age: 20 });
setUser({ ...user, age: 21 });

قيمة ابتدائية مكلفة؟ مرّر دالة

القيمة الابتدائية تُستخدم في أول عرض فقط، لكن التعبير نفسه يُحسب في كل عرض. إن كان حسابها مكلفًا، مرّر دالة فيستدعيها React مرة واحدة:

// ❌ تُقرأ من localStorage وتُحلَّل في كل عرض
const [todos, setTodos] = useState(JSON.parse(localStorage.getItem("todos") ?? "[]"));

// ✅ تُنفَّذ مرة واحدة فقط
const [todos, setTodos] = useState(() => JSON.parse(localStorage.getItem("todos") ?? "[]"));

أخطاء شائعة

  • تعديل الحالة مباشرة (count = 5 أو items.push(...)) بدل دالة التحديث.
  • انتظار القيمة الجديدة فورًا: بعد setCount(5) مباشرة، count في نفس الدالة ما زالت القديمة؛ الجديدة تظهر في العرض التالي.
  • setState بنفس القيمة الحالية: إذا كانت مطابقة للقديمة (Object.is) يتجاهل React التحديث ولا يعيد العرض.

🎯 التالي: التعامل مع الأحداث (Events).

شرح الحالة (State) و useState — React بالعربي
الحالة (State) و useState — React بالعربي · The Code Fix

📚 لمزيد من التعمّق في React، راجِع التوثيق الرسمي لـ React.

هل كان هذا الدرس مفيدًا؟