React: أساسيات State: useState

آخر تحديث: 2026-10-26

الحالة (State) هي ذاكرة المكون. إذا كانت الخصائص (Props) هي معلمات تُعطى لك من قبل عناصر أخرى (للقراءة فقط)، فإن الحالة (State) هي دفتر ملاحظاتك الصغير الخاص (القابل للتعديل). أما useState فهي «رقاقة الذاكرة» التي يثبتها React في المكون.


1. ما ستتعلمه



2. تأملات أثارها عداد

(1) المشكلة: المتغيرات العادية لا تؤدي إلى تحديث واجهة المستخدم

يريد بوب إنشاء عداد بسيط: عندما تنقر على الزر، يزداد الرقم بمقدار 1.

▶ جرّب الكود

اكتشف بوب مشكلةً وهي: المتغيرات العادية لا تُعلم React بضرورة تحديث واجهة المستخدم. في كل مرة يتم فيها إعادة عرض المكون، يتم إعادة تعيين count إلى 0.

(2) حل باستخدام useState

▶ جرّب الكود

قيمة الإرجاع: تُرجع useState مصفوفة [current value, setter function]. بعد استدعاء setCount، يقوم React تلقائيًا بإعادة عرض المكون لعرض أحدث القيم.



3. المفاهيم الأساسية لـ useState

(1) تحليل المهمة

JSX
import { useState } from 'react'

// useState(initialValue) Back [value, setValue]
const [count, setCount] = useState(0)
//      ^      ^          ^
//      |      |          └─ Initial value(Applies only to the first render)
//      |      └─ Update Function(Triggers a re-render after being called)
//      └─ Current status value(Get the latest value on every render)
▶ جرّب الكود
القسم الوصف
count قيمة الحالة الحالية؛ يتم استرداد أحدث قيمة مع كل عملية عرض
setCount دالة التحديث: عند استدعائها → يقوم React بإعادة عرض المكون
useState(0) القيمة الأولية (تُستخدم أثناء عملية العرض الأولى؛ ويتم تجاهلها في عمليات العرض اللاحقة)

(2) آلية التحديث

▶ جرّب الكود

المفهوم الأساسي: setCount(count + 1) تعني «مطالبة React بتحديث count عند عملية العرض التالية»، وليس «تغيير count على الفور». وهذا ما يُسمى التحديث غير المتزامن.

(3) تحديثات وظيفية

إذا كانت الحالة الجديدة تعتمد على الحالة القديمة، فيجب عليك استخدام التحديثات الوظيفية:

▶ جرّب الكود
الطريقة الصيغة الخصائص
التحديث المباشر setCount(count + 1) بسيط، لكن البيانات تُفقد عند إجراء مكالمات متتالية
تحديث وظيفي setCount(prev => prev + 1) دقيق؛ يعمل بشكل صحيح حتى مع المكالمات المتتالية


4. تحديث المصفوفات والكائنات (الثبات)

يتطلب React عدم تعديل الحالة بشكل مباشر. لا تستخدم أبدًا state.push() أو state.name = 'xxx'؛ بل قم بدلاً من ذلك بإنشاء مصفوفة أو كائن جديد لاستبدال القيمة القديمة.

(1) العناصر المطلوب تحديثها

▶ جرّب الكود

(2) تحديث المصفوفة

▶ جرّب الكود

الناتج:

TEXT
الحالة: arr

▶ مثال: جدول مرجعي سريع لعمليات المصفوفات

JSX
// ============================================
// Example:React Array Operations in C 6 Common Scenarios
// ============================================

const [arr, setArr] = useState([1, 2, 3])

// 1. Append to the end
setArr([...arr, 4])           // [1, 2, 3, 4]

// 2. Add to the beginning
setArr([0, ...arr])           // [0, 1, 2, 3]

// 3. Insert in the middle
const insertAt = 1
setArr([...arr.slice(0, insertAt), 99, ...arr.slice(insertAt)])
                              // [1, 99, 2, 3]

// 4. Delete Element(filter)
setArr(arr.filter(n => n !== 2))  // [1, 3]

// 5. Update Element(map)
setArr(arr.map(n => n === 2 ? 22 : n))  // [1, 22, 3]

// 6. Sort(Copy first, then sort)
setArr([...arr].sort((a, b) => b - a))  // [3, 2, 1]
▶ جرّب الكود

الناتج:

TEXT
عمليات على حالة المصفوفة: push → إضافة عنصر، filter → حذف عنصر، map → تحديث عنصر. كل عملية تُعيد مرجع مصفوفة جديدًا حتى يعيد React العرض


5. متغيرات الحالة المتعددة

يمكن أن يحتوي المكون على متغيرات حالة متعددة. يُنصح بتقسيمها وفقًا للمنطق بدلاً من حشرها في كائن واحد كبير:

JSX
function RegistrationForm() {
  // ✅ Recommendations:Logical Breakdown
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [errors, setErrors] = useState({})

  // ❌ Not recommended:All states are stored in a single object
  const [form, setForm] = useState({
    name: '', email: '', password: '',
    isSubmitting: false, errors: {}
  })
  // Expand the entire object when updating,Fields that are easy to overlook
}
▶ جرّب الكود
الاستراتيجية المزايا العيوب
تقسيمها إلى عدة useState تحديثات دقيقة، وآمنة من حيث الأنواع، وسهلة القراءة وجود عدد كبير جدًا من المتغيرات عند وجود الكثير من الحالات
مدمجة في useState واحد ملائمة لتحديث حقول متعددة في آن واحد صيغة التحديث معقدة ومن السهل نسيان توسيعها

توصية: استخدم عدة مثيلات من useState للحالات المستقلة (مثل حقول الإدخال، ومؤشرات التحميل، ورسائل الخطأ)؛ أما الحقول المرتبطة منطقياً (مثل جميع الحقول في ملف تعريف المستخدم) فيمكن دمجها في كائن واحد.



6. النهوض بالدولة

عندما تحتاج عدة مكونات إلى مشاركة الحالة نفسها، قم بنقل الحالة إلى أقرب مكون أب مشترك بينها.

100%
graph TB
    subgraph "Before the status upgrade(Data is not shared)"
        A[Parent Component App] --- B[Child component A<br/>Have their own count]
        A --- C[Child component B<br/>Have their own count]
    end
    
    subgraph "After the status upgrade(Data Sharing)"
        D[Parent Component App<br/>**count Here**] --- E[Child component A<br/>Read count, Call setCount]
        D --- F[Child component B<br/>Read count, Call setCount]
    end

الناتج:

TEXT
الحالة: arr (setter: setArr)

▶ مثال: التطبيق العملي لتعزيز الحالة

▶ جرّب الكود

الناتج:

TEXT
عند إدخال 100 بالدرجة المئوية → تُعرض تلقائيًا 212.0 بالفهرنهايت. يعرض "100°C = 212.0°F". حقلا الإدخال يبقيان متزامنين.


7. مثال كامل: عداد سلة التسوق

▶ عرض المثال القابل للتشغيل (96 سطرًا)
▶ جرّب الكود

الناتج:

TEXT
العنوان الفرعي: "Temperature Converter". يعرض: "Celsius(°C):". الحالة: temperature (setter: setTemperature)

مسار التفاعل:

  • اضغط على +/− لتعديل الكمية؛ ويتم تحديث المجموع الفرعي والمجموع الكلي في الوقت الفعلي
  • انقر على ✕ لحذف عنصر؛ اعرض رسالة توضيحية سهلة الفهم عندما تكون سلة التسوق فارغة
  • أدخل الرمز الترويجي REACT2026 لتوفير 20 يوان

▶ المثال 3: تحديث حالة كائن — تعديل معلومات المستخدم

JSX
function UserEditor() {
  const [user, setUser] = useState({ name: 'Alice', email: 'alice@test.com', age: 28 })

  function updateField(field, value) {
    setUser(prev => ({ ...prev, [field]: value }))
  }

  return (
    <div style={{ maxWidth: 400, margin: '0 auto' }}>
      <h3>Edit Profile</h3>
      <input value={user.name} onChange={e => updateField('name', e.target.value)}
        placeholder="Name" style={{ width: '100%', padding: 8, marginBottom: 8, borderRadius: 4 }} />
      <input value={user.email} onChange={e => updateField('email', e.target.value)}
        placeholder="Email" style={{ width: '100%', padding: 8, marginBottom: 8, borderRadius: 4 }} />
      <input type="number" value={user.age} onChange={e => updateField('age', Number(e.target.value))}
        placeholder="Age" style={{ width: '100%', padding: 8, marginBottom: 8, borderRadius: 4 }} />
      <pre style={{ background: '#f5f5f5', padding: 12, borderRadius: 4, fontSize: 13 }}>
        {JSON.stringify(user, null, 2)}
      </pre>
    </div>
  )
}
▶ جرّب الكود

الناتج:

TEXT
الحالة: address. حقول الإدخال: Street، City، ZIP

الناتج:

TEXT
يعرض: "Edit Profile". الحالة: user (setter: setUser). الإدخال: Name، Email، Age

▶ المثال 4: حالات الكائنات المتداخلة — إدارة العناوين

▶ جرّب الكود

الناتج:

TEXT
نموذج عنوان الشحن: Street، City، ZIP، قائمة منسدلة للدولة (US/CN/JP)، مربع اختيار "Primary address". كل الحقول تُحدث الحالة بشكل تفاعلي.

الناتج:

TEXT
يعرض: "Shipping Address". الحالة: address (setter: setAddress). الإدخال: Street، City، ZIP. القائمة المنسدلة: United States، China، Japan

▶ المثال 5: التحديثات الوظيفية تحل مشكلة التحديثات المجمعة

▶ جرّب الكود

الناتج:

TEXT
Score: 0، Multiplier: x1. الأزرار +10/+50/+100 تضيف نقاطًا بمقدار (النقاط × المضاعف). "2x Multiplier" يضاعف المضاعف (حتى x8). Reset → Score: 0، x1


❓ أسئلة شائعة

س ما الفرق في الأداء بين useState والمتغيرات العادية؟
ج تتسبب useState في عبء إضافي (تتبع التغييرات، وجدولة العرض)، لذا يجب استخدامها فقط في الحالات التي «يتم فيها تشغيل تحديثات واجهة المستخدم عند حدوث تغييرات». إذا تغيرت المتغير ولكنها لا تتطلب تحديثًا لواجهة المستخدم (مثل معرّف المؤقت أو موضع التمرير)، فإن استخدام useRef (الدرس 10) يكون أكثر ملاءمة.
س كم عدد useStates التي يمكن أن يتضمنها مكون واحد؟ وهل توجد أي مشكلات في الأداء؟
ج لا يوجد حد أقصى لعددها. توصي الوثائق الرسمية لـ React بتقسيم العناصر إلى عدة useStates بناءً على المنطق بدلاً من استخدام كائن واحد كبير. كل استدعاء لـ useState يمثل «وحدة حالة»، ويمكن لـ React التعامل بكفاءة مع عدد كبير من useStates. عادةً ما تحتوي المكونات الشائعة على 3–8 useStates.
س هل يتم تحديث setState بشكل متزامن أم غير متزامن؟
ج قبل الإصدار React 18، كان setState يُجمع تلقائيًا ضمن معالجات الأحداث، ولكنه كان متزامنًا ضمن استدعاءات setTimeout وPromise. أدخلت React 18 ميزة التجميع التلقائي، لذا أصبحت setState الآن تُعالج بشكل غير متزامن على دفعات بغض النظر عما إذا تم استدعاؤها داخل معالج أحداث أو setTimeout أو Promise أو استدعاء رد فعل fetch. إذا كنت بحاجة ماسة للوصول إلى DOM المحدث بشكل متزامن، فيمكنك استخدام flushSync(() => setState(...)).

📖 ملخص


📝 تمارين

  1. تمرين أساسي (مستوى الصعوبة ⭐): أنشئ مكونًا باسم LikeButton يتبدل بين الحالتين ❤️ و🤍 عند النقر عليه ويعرض عدد الإعجابات.
  2. تمرين متقدم (مستوى الصعوبة ⭐⭐): أنشئ مكونًا ExpenseTracker يستخدم useState لإدارة قائمة بالمصروفات (الوصف، المبلغ، التاريخ)، ويدعم إضافة العناصر وحذفها.
  3. التحدي (الصعوبة: ⭐⭐⭐): قم بإنشاء مكون ColorPicker يستخدم ثلاث حالات من useState لإدارة قيم أشرطة التمرير R و G و B (0–255)، ويعرض معاينة اللون في الوقت الفعلي ورمز اللون السداسي العشري.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%