React: أساسيات State: useState
آخر تحديث: 2026-10-26
الحالة (State) هي ذاكرة المكون. إذا كانت الخصائص (Props) هي معلمات تُعطى لك من قبل عناصر أخرى (للقراءة فقط)، فإن الحالة (State) هي دفتر ملاحظاتك الصغير الخاص (القابل للتعديل). أما useState فهي «رقاقة الذاكرة» التي يثبتها React في المكون.
1. ما ستتعلمه
- ما هي «الدولة»؟ ولماذا نحتاج إليها؟
- الاستخدام الأساسي لـ useState
- الطريقة الصحيحة لتحديث حالات المصفوفات والكائنات (الثبات)
- إدارة متغيرات الحالة المتعددة
- الارتقاء بمستوى الدولة
2. تأملات أثارها عداد
(1) المشكلة: المتغيرات العادية لا تؤدي إلى تحديث واجهة المستخدم
يريد بوب إنشاء عداد بسيط: عندما تنقر على الزر، يزداد الرقم بمقدار 1.
▶ جرّب الكوداكتشف بوب مشكلةً وهي: المتغيرات العادية لا تُعلم React بضرورة تحديث واجهة المستخدم. في كل مرة يتم فيها إعادة عرض المكون، يتم إعادة تعيين count إلى 0.
(2) حل باستخدام useState
▶ جرّب الكود
قيمة الإرجاع: تُرجع useState مصفوفة [current value, setter function]. بعد استدعاء setCount، يقوم React تلقائيًا بإعادة عرض المكون لعرض أحدث القيم.
3. المفاهيم الأساسية لـ useState
(1) تحليل المهمة
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) تحديث المصفوفة
▶ جرّب الكودالناتج:
الحالة: arr
▶ مثال: جدول مرجعي سريع لعمليات المصفوفات
// ============================================
// 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]
الناتج:
عمليات على حالة المصفوفة: push → إضافة عنصر، filter → حذف عنصر، map → تحديث عنصر. كل عملية تُعيد مرجع مصفوفة جديدًا حتى يعيد React العرض
5. متغيرات الحالة المتعددة
يمكن أن يحتوي المكون على متغيرات حالة متعددة. يُنصح بتقسيمها وفقًا للمنطق بدلاً من حشرها في كائن واحد كبير:
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. النهوض بالدولة
عندما تحتاج عدة مكونات إلى مشاركة الحالة نفسها، قم بنقل الحالة إلى أقرب مكون أب مشترك بينها.
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
الناتج:
الحالة: arr (setter: setArr)
▶ مثال: التطبيق العملي لتعزيز الحالة
▶ جرّب الكودالناتج:
عند إدخال 100 بالدرجة المئوية → تُعرض تلقائيًا 212.0 بالفهرنهايت. يعرض "100°C = 212.0°F". حقلا الإدخال يبقيان متزامنين.
7. مثال كامل: عداد سلة التسوق
▶ عرض المثال القابل للتشغيل (96 سطرًا)
الناتج:
العنوان الفرعي: "Temperature Converter". يعرض: "Celsius(°C):". الحالة: temperature (setter: setTemperature)
مسار التفاعل:
- اضغط على +/− لتعديل الكمية؛ ويتم تحديث المجموع الفرعي والمجموع الكلي في الوقت الفعلي
- انقر على ✕ لحذف عنصر؛ اعرض رسالة توضيحية سهلة الفهم عندما تكون سلة التسوق فارغة
- أدخل الرمز الترويجي
REACT2026لتوفير 20 يوان
▶ المثال 3: تحديث حالة كائن — تعديل معلومات المستخدم
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>
)
}
الناتج:
الحالة: address. حقول الإدخال: Street، City، ZIP
الناتج:
يعرض: "Edit Profile". الحالة: user (setter: setUser). الإدخال: Name، Email، Age
▶ المثال 4: حالات الكائنات المتداخلة — إدارة العناوين
▶ جرّب الكودالناتج:
نموذج عنوان الشحن: Street، City، ZIP، قائمة منسدلة للدولة (US/CN/JP)، مربع اختيار "Primary address". كل الحقول تُحدث الحالة بشكل تفاعلي.
الناتج:
يعرض: "Shipping Address". الحالة: address (setter: setAddress). الإدخال: Street، City، ZIP. القائمة المنسدلة: United States، China، Japan
▶ المثال 5: التحديثات الوظيفية تحل مشكلة التحديثات المجمعة
▶ جرّب الكودالناتج:
Score: 0، Multiplier: x1. الأزرار +10/+50/+100 تضيف نقاطًا بمقدار (النقاط × المضاعف). "2x Multiplier" يضاعف المضاعف (حتى x8). Reset → Score: 0، x1
❓ أسئلة شائعة
useState والمتغيرات العادية؟useState في عبء إضافي (تتبع التغييرات، وجدولة العرض)، لذا يجب استخدامها فقط في الحالات التي «يتم فيها تشغيل تحديثات واجهة المستخدم عند حدوث تغييرات». إذا تغيرت المتغير ولكنها لا تتطلب تحديثًا لواجهة المستخدم (مثل معرّف المؤقت أو موضع التمرير)، فإن استخدام useRef (الدرس 10) يكون أكثر ملاءمة.useStates التي يمكن أن يتضمنها مكون واحد؟ وهل توجد أي مشكلات في الأداء؟useStates بناءً على المنطق بدلاً من استخدام كائن واحد كبير. كل استدعاء لـ useState يمثل «وحدة حالة»، ويمكن لـ React التعامل بكفاءة مع عدد كبير من useStates. عادةً ما تحتوي المكونات الشائعة على 3–8 useStates.setState بشكل متزامن أم غير متزامن؟setState يُجمع تلقائيًا ضمن معالجات الأحداث، ولكنه كان متزامنًا ضمن استدعاءات setTimeout وPromise. أدخلت React 18 ميزة التجميع التلقائي، لذا أصبحت setState الآن تُعالج بشكل غير متزامن على دفعات بغض النظر عما إذا تم استدعاؤها داخل معالج أحداث أو setTimeout أو Promise أو استدعاء رد فعل fetch. إذا كنت بحاجة ماسة للوصول إلى DOM المحدث بشكل متزامن، فيمكنك استخدام flushSync(() => setState(...)).📖 ملخص
- «الحالة» هي «ذاكرة» المكون؛ وعندما تتغير، فإنها تؤدي تلقائيًا إلى تحديث واجهة المستخدم
useState(initialValue)تُرجع المصفوفة[value, setValue]- الثبات: لا تقم أبدًا بتعديل الحالة مباشرةً؛ بل قم بدلاً من ذلك بإنشاء كائن أو مصفوفة جديدة لتحل محلها.
- التحديث الوظيفي
setCount(prev => prev + 1)يكون أكثر دقة عند الاعتماد على القيم القديمة - رفع الحالة: عندما تحتاج عدة مكونات فرعية إلى مشاركة البيانات، يتم رفع الحالة إلى مكون أب مشترك.
📝 تمارين
- تمرين أساسي (مستوى الصعوبة ⭐): أنشئ مكونًا باسم
LikeButtonيتبدل بين الحالتين ❤️ و🤍 عند النقر عليه ويعرض عدد الإعجابات. - تمرين متقدم (مستوى الصعوبة ⭐⭐): أنشئ مكونًا
ExpenseTrackerيستخدمuseStateلإدارة قائمة بالمصروفات (الوصف، المبلغ، التاريخ)، ويدعم إضافة العناصر وحذفها. - التحدي (الصعوبة: ⭐⭐⭐): قم بإنشاء مكون
ColorPickerيستخدم ثلاث حالات منuseStateلإدارة قيم أشرطة التمرير R و G و B (0–255)، ويعرض معاينة اللون في الوقت الفعلي ورمز اللون السداسي العشري.