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

State في React — دليل شامل useState 2026

دليل عملي مفصل لإدارة الحالة (State) في React — useState، التحديث، الحالات المعقدة، مع تمارين وحلول

في المقال السابق، تعلمت المكونات وكيفية تمرير Props. لكن Props ثابتة (لا تتغير). الآن سنتعلم State — وهي البيانات التي تتغير مع تفاعل المستخدم.

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

ما هو State؟

State هي بيانات متغيرة داخل المكوّنة. عندما تتغير، React تُعيد رسم المكوّنة تلقائياً.

تشبيه بسيط: تخيل أن State هي ذاكرة المكوّنة. الـ Props هي "ما يُعطى لها"، والـ State هي "ما تتذكره".

الفرق بين Props و State

المعيارPropsState
المصدرمن الأبداخلي
التغيير❌ لا يتغير✅ يتغير
الاستخدامبيانات ثابتةبيانات تفاعلية
المثالاسم المستخدمعدد النقرات

useState Hook

useState هو Hook يسمح بإضافة State للمكونات الوظيفية.

الصيغة:

const [state, setState] = useState(initialValue);

شرح:

  • state: القيمة الحالية.
  • setState: دالة لتحديث القيمة.
  • initialValue: القيمة الأولية.

مثال بسيط:

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

const [count, setCount] = useState(0);
const [price, setPrice] = useState(99.99);

2. String

const [name, setName] = useState("");
const [email, setEmail] = useState("");

3. Boolean

const [isOpen, setIsOpen] = useState(false);
const [isDark, setIsDark] = useState(true);

4. Array

const [items, setItems] = useState<string[]>([]);
const [numbers, setNumbers] = useState<number[]>([1, 2, 3]);

5. Object

const [user, setUser] = useState({
  name: "أحمد",
  age: 25,
});

6. Union Types

type Status = "idle" | "loading" | "success" | "error";
const [status, setStatus] = useState<Status>("idle");

تحديث State

1. تحديث مباشر

setCount(10);
setName("محمد");
setIsOpen(true);

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

❌ خطأ:

setCount(count + 1);
setCount(count + 1);  // لا يعمل! يضيف 1 فقط

✅ صحيح:

setCount((prev) => prev + 1);
setCount((prev) => prev + 1);  // يضيف 2

السبب: React تجمّع التحديثات (batching) للأداء.

3. تحديث Array

❌ خطأ (لا يعمل):

items.push("جديد");
setItems(items);

✅ صحيح:

// إضافة
setItems([...items, "جديد"]);

// حذف
setItems(items.filter((item) => item !== "جديد"));

// تعديل
setItems(items.map((item) => (item === "قديم" ? "جديد" : item)));

4. تحديث Object

❌ خطأ:

user.name = "محمد";
setUser(user);

✅ صحيح:

setUser({ ...user, name: "محمد" });

مثال عملي: تطبيق عداد

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;

مثال عملي: نموذج إدخال

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>
  );
}

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

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 بسيط

const [count, setCount] = useState<number>(0);
const [name, setName] = useState<string>("");
const [isOpen, setIsOpen] = useState<boolean>(false);

2. State مع Union

type Status = "idle" | "loading" | "success" | "error";
const [status, setStatus] = useState<Status>("idle");

3. State مع Array

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

const [todos, setTodos] = useState<Todo[]>([]);

4. State مع Object

interface User {
  name: string;
  age: number;
}

const [user, setUser] = useState<User>({ name: "", age: 0 });

5. State مع Null

const [user, setUser] = useState<User | null>(null);

Lazy Initial State

إذا كانت القيمة الأولية تحتاج حساباً:

// ❌ بطيء (يُحسب في كل render):
const [data, setData] = useState(expensiveCalculation());

// ✅ سريع (يُحسب مرة واحدة):
const [data, setData] = useState(() => expensiveCalculation());

رفع الحالة (Lifting State Up)

عندما تحتاج مكونتان مشاركة State، ارفعه للمكوّن الأب.

مثال:

// المكوّن الأب
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.

الحل:

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: نموذج تسجيل

أنشئ نموذجاً بحقول: الاسم، البريد، كلمة المرور.

الحل:

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 (زر تبديل)

أنشئ زراً يبدّل بين "مفعّل" و "معطّل".

الحل:

function Toggle() {
  const [isOn, setIsOn] = useState(false);
  return (
    <button onClick={() => setIsOn(!isOn)}>
      {isOn ? "✅ مفعّل" : "❌ معطّل"}
    </button>
  );
}

تمرين 4: قائمة تسوق

أنشئ قائمة تسوق مع إضافة وحذف.

الحل:

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: تبديل اللون

أنشئ زراً يبدّل لون خلفية بين الأبيض والأسود.

الحل:

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.

الحل:

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: نموذج معاينة مباشرة

أنشئ نموذجاً يعرض النص أثناء الكتابة.

الحل:

function LivePreview() {
  const [text, setText] = useState("");
  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <p>المعاينة: {text}</p>
    </div>
  );
}

تمرين 8: قائمة مهام كاملة

أنشئ قائمة مهام مع إضافة، حذف، وتعليم كمكتمل.

الحل:

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 لا يتحدّث

السبب: تحديث مباشر بدلاً من دالة التحديث.

الحل:

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

🔴 المشكلة 2: Array لا يتحدّث

السبب: استخدام push بدلاً من spread.

الحل:

setItems([...items, newItem]);

🔴 المشكلة 3: Object لا يتحدّث

السبب: تعديل مباشر.

الحل:

setUser({ ...user, name: "محمد" });

🔴 المشكلة 4: حلقة لا نهائية

السبب: استدعاء setState داخل render.

الحل: استخدم useEffect (سنتعلمه لاحقاً).

جدول أوامر useState

الأمرالوظيفة
useState(initial)تعريف State
setState(value)تعيين قيمة
setState(prev => ...)تحديث بناءً على السابق
useState(() => ...)Lazy initial state

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

المهمةالحالة
فهم State و useState⬜
الفرق بين Props و State⬜
تحديث State بشكل صحيح⬜
State مع Array و Object⬜
State مع TypeScript⬜
بناء قائمة مهام⬜
حل التمارين الثمانية⬜

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

الآن بعد أن أتقنت State، أنت جاهز للمقال التالي:

  1. الأحداث (Events) — التعامل مع تفاعل المستخدم.
  2. النماذج (Forms) — إدارة المدخلات.
  3. useEffect — التأثيرات الجانبية.

الخلاصة

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

  • ✅ ما هو State ولماذا نحتاجه.
  • ✅ الفرق بين Props و State.
  • ✅ useState Hook وكيفية استخدامه.
  • ✅ تحديث State بشكل صحيح.
  • ✅ State مع Array و Object.
  • ✅ رفع الحالة (Lifting State Up).
  • ✅ حل 8 تمارين عملية.

تذكر: State هو ما يجعل تطبيقات React تفاعلية. أتقنه جيداً.

هل أتقنت State؟ شاركنا في التعليقات!

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

React

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

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

React

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

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

React

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

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