React
State في React — دليل شامل useState 2026
📅 2026-10-13⏱ 9 دقائق قراءة
في المقال السابق، تعلمت المكونات وكيفية تمرير Props. لكن Props **ثابتة** (لا تتغير). الآن سنتعلم **State** — وهي البيانات التي **تتغير** مع تفاعل المستخدم.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم `useState` وكيفية إدارة الحالة في React، مع تمارين وحلول.
## ما هو State؟
**State** هي **بيانات متغيرة** داخل المكوّنة. عندما تتغير، React **تُعيد رسم** المكوّنة تلقائياً.
**تشبيه بسيط:** تخيل أن State هي **ذاكرة** المكوّنة. الـ Props هي "ما يُعطى لها"، والـ State هي "ما تتذكره".
## الفرق بين Props و State
<table>
<thead>
<tr>
<th>المعيار</th>
<th>Props</th>
<th>State</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>المصدر</strong></td>
<td>من الأب</td>
<td>داخلي</td>
</tr>
<tr>
<td><strong>التغيير</strong></td>
<td>❌ لا يتغير</td>
<td>✅ يتغير</td>
</tr>
<tr>
<td><strong>الاستخدام</strong></td>
<td>بيانات ثابتة</td>
<td>بيانات تفاعلية</td>
</tr>
<tr>
<td><strong>المثال</strong></td>
<td>اسم المستخدم</td>
<td>عدد النقرات</td>
</tr>
</tbody>
</table>
## useState Hook
`useState` هو **Hook** يسمح بإضافة State للمكونات الوظيفية.
### الصيغة:
```tsx
const [state, setState] = useState(initialValue);
```
**شرح:**
- **`state`:** القيمة الحالية.
- **`setState`:** دالة لتحديث القيمة.
- **`initialValue`:** القيمة الأولية.
### مثال بسيط:
```tsx
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>العدد: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
```
**شرح:**
1. `useState(0)` → يبدأ العدد بـ 0.
2. عند الضغط على الزر → `setCount(count + 1)`.
3. React تُحدّث `count` وتُعيد رسم المكوّنة.
## أنواع State
### 1. Number
```tsx
const [count, setCount] = useState(0);
const [price, setPrice] = useState(99.99);
```
### 2. String
```tsx
const [name, setName] = useState("");
const [email, setEmail] = useState("");
```
### 3. Boolean
```tsx
const [isOpen, setIsOpen] = useState(false);
const [isDark, setIsDark] = useState(true);
```
### 4. Array
```tsx
const [items, setItems] = useState<string[]>([]);
const [numbers, setNumbers] = useState<number[]>([1, 2, 3]);
```
### 5. Object
```tsx
const [user, setUser] = useState({
name: "أحمد",
age: 25,
});
```
### 6. Union Types
```tsx
type Status = "idle" | "loading" | "success" | "error";
const [status, setStatus] = useState<Status>("idle");
```
## تحديث State
### 1. تحديث مباشر
```tsx
setCount(10);
setName("محمد");
setIsOpen(true);
```
### 2. تحديث بناءً على القيمة السابقة
**❌ خطأ:**
```tsx
setCount(count + 1);
setCount(count + 1); // لا يعمل! يضيف 1 فقط
```
**✅ صحيح:**
```tsx
setCount((prev) => prev + 1);
setCount((prev) => prev + 1); // يضيف 2
```
**السبب:** React تجمّع التحديثات (batching) للأداء.
### 3. تحديث Array
**❌ خطأ (لا يعمل):**
```tsx
items.push("جديد");
setItems(items);
```
**✅ صحيح:**
```tsx
// إضافة
setItems([...items, "جديد"]);
// حذف
setItems(items.filter((item) => item !== "جديد"));
// تعديل
setItems(items.map((item) => (item === "قديم" ? "جديد" : item)));
```
### 4. تحديث Object
**❌ خطأ:**
```tsx
user.name = "محمد";
setUser(user);
```
**✅ صحيح:**
```tsx
setUser({ ...user, name: "محمد" });
```
## مثال عملي: تطبيق عداد
```tsx
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const increment = () => setCount((prev) => prev + 1);
const decrement = () => setCount((prev) => prev - 1);
const reset = () => setCount(0);
return (
<div className="counter">
<h2>العدد: {count}</h2>
<div className="buttons">
<button onClick={decrement}>-</button>
<button onClick={reset}>إعادة</button>
<button onClick={increment}>+</button>
</div>
</div>
);
}
export default Counter;
```
## مثال عملي: نموذج إدخال
```tsx
import { useState } from "react";
function Form() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
alert(`الاسم: ${name}\nالبريد: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="الاسم"
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="البريد الإلكتروني"
/>
<button type="submit">إرسال</button>
</form>
);
}
```
## مثال عملي: قائمة مهام
```tsx
import { useState } from "react";
interface Todo {
id: number;
text: string;
completed: boolean;
}
function TodoApp() {
const [todos, setTodos] = useState<Todo[]>([]);
const [input, setInput] = useState("");
const addTodo = () => {
if (input.trim() === "") return;
setTodos([
...todos,
{ id: Date.now(), text: input, completed: false },
]);
setInput("");
};
const toggleTodo = (id: number) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
const deleteTodo = (id: number) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
return (
<div className="todo-app">
<h1>📝 قائمة المهام</h1>
<div className="input-group">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && addTodo()}
placeholder="أضف مهمة..."
/>
<button onClick={addTodo}>إضافة</button>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{ textDecoration: todo.completed ? "line-through" : "none" }}>
{todo.text}
</span>
<button onClick={() => deleteTodo(todo.id)}>🗑️</button>
</li>
))}
</ul>
</div>
);
}
```
## State مع TypeScript
### 1. State بسيط
```tsx
const [count, setCount] = useState<number>(0);
const [name, setName] = useState<string>("");
const [isOpen, setIsOpen] = useState<boolean>(false);
```
### 2. State مع Union
```tsx
type Status = "idle" | "loading" | "success" | "error";
const [status, setStatus] = useState<Status>("idle");
```
### 3. State مع Array
```tsx
interface Todo {
id: number;
text: string;
}
const [todos, setTodos] = useState<Todo[]>([]);
```
### 4. State مع Object
```tsx
interface User {
name: string;
age: number;
}
const [user, setUser] = useState<User>({ name: "", age: 0 });
```
### 5. State مع Null
```tsx
const [user, setUser] = useState<User | null>(null);
```
## Lazy Initial State
إذا كانت القيمة الأولية تحتاج حساباً:
```tsx
// ❌ بطيء (يُحسب في كل render):
const [data, setData] = useState(expensiveCalculation());
// ✅ سريع (يُحسب مرة واحدة):
const [data, setData] = useState(() => expensiveCalculation());
```
## رفع الحالة (Lifting State Up)
عندما تحتاج مكونتان مشاركة State، ارفعه للمكوّن الأب.
**مثال:**
```tsx
// المكوّن الأب
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<Child1 count={count} />
<Child2 count={count} setCount={setCount} />
</div>
);
}
function Child1({ count }: { count: number }) {
return <p>العدد: {count}</p>;
}
function Child2({ count, setCount }: { count: number; setCount: (n: number) => void }) {
return <button onClick={() => setCount(count + 1)}>+1</button>;
}
```
## تمارين عملية
### تمرين 1: عداد بسيط
أنشئ عداداً مع زر +1 و -1.
**الحل:**
```tsx
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
);
}
```
### تمرين 2: نموذج تسجيل
أنشئ نموذجاً بحقول: الاسم، البريد، كلمة المرور.
**الحل:**
```tsx
function RegisterForm() {
const [form, setForm] = useState({ name: "", email: "", password: "" });
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
return (
<form>
<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<input name="password" type="password" value={form.password} onChange={handleChange} />
</form>
);
}
```
### تمرين 3: Toggle (زر تبديل)
أنشئ زراً يبدّل بين "مفعّل" و "معطّل".
**الحل:**
```tsx
function Toggle() {
const [isOn, setIsOn] = useState(false);
return (
<button onClick={() => setIsOn(!isOn)}>
{isOn ? "✅ مفعّل" : "❌ معطّل"}
</button>
);
}
```
### تمرين 4: قائمة تسوق
أنشئ قائمة تسوق مع إضافة وحذف.
**الحل:**
```tsx
function ShoppingList() {
const [items, setItems] = useState<string[]>([]);
const [input, setInput] = useState("");
const add = () => {
if (input) {
setItems([...items, input]);
setInput("");
}
};
return (
<div>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={add}>إضافة</button>
<ul>
{items.map((item, i) => (
<li key={i}>
{item}
<button onClick={() => setItems(items.filter((_, j) => j !== i))}>❌</button>
</li>
))}
</ul>
</div>
);
}
```
### تمرين 5: تبديل اللون
أنشئ زراً يبدّل لون خلفية بين الأبيض والأسود.
**الحل:**
```tsx
function ColorToggle() {
const [isDark, setIsDark] = useState(false);
return (
<div style={{ background: isDark ? "#000" : "#fff", color: isDark ? "#fff" : "#000", padding: 40 }}>
<button onClick={() => setIsDark(!isDark)}>
{isDark ? "☀️ فاتح" : "🌙 داكن"}
</button>
</div>
);
}
```
### تمرين 6: عداد مع حد أقصى
أنشئ عداداً لا يزيد عن 10.
**الحل:**
```tsx
function LimitedCounter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(Math.min(10, count + 1))}>+</button>
<button onClick={() => setCount(Math.max(0, count - 1))}>-</button>
</div>
);
}
```
### تمرين 7: نموذج معاينة مباشرة
أنشئ نموذجاً يعرض النص أثناء الكتابة.
**الحل:**
```tsx
function LivePreview() {
const [text, setText] = useState("");
return (
<div>
<input value={text} onChange={(e) => setText(e.target.value)} />
<p>المعاينة: {text}</p>
</div>
);
}
```
### تمرين 8: قائمة مهام كاملة
أنشئ قائمة مهام مع إضافة، حذف، وتعليم كمكتمل.
**الحل:**
```tsx
interface Todo {
id: number;
text: string;
completed: boolean;
}
function TodoList() {
const [todos, setTodos] = useState<Todo[]>([]);
const [input, setInput] = useState("");
const add = () => {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input, completed: false }]);
setInput("");
}
};
return (
<div>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={add}>إضافة</button>
<ul>
{todos.map((t) => (
<li key={t.id}>
<input
type="checkbox"
checked={t.completed}
onChange={() =>
setTodos(todos.map((x) => (x.id === t.id ? { ...x, completed: !x.completed } : x)))
}
/>
<span style={{ textDecoration: t.completed ? "line-through" : "none" }}>{t.text}</span>
<button onClick={() => setTodos(todos.filter((x) => x.id !== t.id))}>🗑️</button>
</li>
))}
</ul>
</div>
);
}
```
## حل المشاكل الشائعة
### 🔴 المشكلة 1: State لا يتحدّث
**السبب:** تحديث مباشر بدلاً من دالة التحديث.
**الحل:**
```tsx
setCount((prev) => prev + 1);
```
### 🔴 المشكلة 2: Array لا يتحدّث
**السبب:** استخدام `push` بدلاً من spread.
**الحل:**
```tsx
setItems([...items, newItem]);
```
### 🔴 المشكلة 3: Object لا يتحدّث
**السبب:** تعديل مباشر.
**الحل:**
```tsx
setUser({ ...user, name: "محمد" });
```
### 🔴 المشكلة 4: حلقة لا نهائية
**السبب:** استدعاء `setState` داخل render.
**الحل:** استخدم `useEffect` (سنتعلمه لاحقاً).
## جدول أوامر useState
<table>
<thead>
<tr>
<th>الأمر</th>
<th>الوظيفة</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>useState(initial)</code></td>
<td>تعريف State</td>
</tr>
<tr>
<td><code>setState(value)</code></td>
<td>تعيين قيمة</td>
</tr>
<tr>
<td><code>setState(prev => ...)</code></td>
<td>تحديث بناءً على السابق</td>
</tr>
<tr>
<td><code>useState(() => ...)</code></td>
<td>Lazy initial state</td>
</tr>
</tbody>
</table>
## قائمة تحقق نهائية
<table>
<thead>
<tr>
<th>المهمة</th>
<th>الحالة</th>
</tr>
</thead>
<tbody>
<tr>
<td>فهم State و useState</td>
<td>⬜</td>
</tr>
<tr>
<td>الفرق بين Props و State</td>
<td>⬜</td>
</tr>
<tr>
<td>تحديث State بشكل صحيح</td>
<td>⬜</td>
</tr>
<tr>
<td>State مع Array و Object</td>
<td>⬜</td>
</tr>
<tr>
<td>State مع TypeScript</td>
<td>⬜</td>
</tr>
<tr>
<td>بناء قائمة مهام</td>
<td>⬜</td>
</tr>
<tr>
<td>حل التمارين الثمانية</td>
<td>⬜</td>
</tr>
</tbody>
</table>
## ماذا بعد هذا المقال؟
الآن بعد أن أتقنت State، أنت جاهز للمقال التالي:
1. **الأحداث (Events)** — التعامل مع تفاعل المستخدم.
2. **النماذج (Forms)** — إدارة المدخلات.
3. **useEffect** — التأثيرات الجانبية.
## الخلاصة
في هذا المقال، تعلمت:
- ✅ ما هو State ولماذا نحتاجه.
- ✅ الفرق بين Props و State.
- ✅ `useState` Hook وكيفية استخدامه.
- ✅ تحديث State بشكل صحيح.
- ✅ State مع Array و Object.
- ✅ رفع الحالة (Lifting State Up).
- ✅ حل 8 تمارين عملية.
**تذكر:** State هو ما يجعل تطبيقات React **تفاعلية**. أتقنه جيداً.
**هل أتقنت State؟ شاركنا في التعليقات!**