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

الأحداث والنماذج في React — دليل شامل 2026

دليل عملي مفصل للأحداث (Events) والنماذج (Forms) في React — onClick, onChange, onSubmit، مع تمارين وحلول

في المقال السابق، تعلمت State وكيفية إدارة البيانات المتغيرة. الآن سنتعلم الأحداث (Events) و النماذج (Forms) — وهي الطريقة التي يتفاعل بها المستخدم مع تطبيقك.

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

ما هي الأحداث؟

الأحداث (Events) هي تفاعلات المستخدم مع الصفحة:

  • النقر (click).
  • الكتابة (input).
  • الإرسال (submit).
  • المرور (mouseover).
  • الضغط على المفاتيح (keydown).

الفرق بين HTML و React:

HTMLReact
onclick="..."onClick={...}
أحرف صغيرةcamelCase
نص (string)دالة (function)

الأحداث الشائعة

الحدثالوصف
onClickنقر بالفأرة
onDoubleClickنقر مزدوج
onChangeتغيير في حقل إدخال
onSubmitإرسال نموذج
onFocusتركيز على حقل
onBlurخروج من حقل
onKeyDownضغط مفتاح
onKeyUpرفع مفتاح
onMouseEnterدخول الفأرة
onMouseLeaveخروج الفأرة

أحداث النقر (onClick)

1. دالة بسيطة

function Button() {
  const handleClick = () => {
    alert("تم النقر!");
  };

  return <button onClick={handleClick}>اضغط</button>;
}

2. دالة سهمية مباشرة

<button onClick={() => alert("تم النقر!")}>اضغط</button>

⚠️ ملاحظة: onClick={handleClick} بدون () — تمرر الدالة، لا تستدعيها.

3. تمرير معاملات

function Button() {
  const handleClick = (name: string) => {
    alert(`مرحباً ${name}`);
  };

  return (
    <button onClick={() => handleClick("أحمد")}>
      اضغط
    </button>
  );
}

أحداث الإدخال (onChange)

1. حقل بسيط

function Input() {
  const [value, setValue] = useState("");

  return (
    <input
      type="text"
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

شرح:

  • value={value}: القيمة الحالية (Controlled Component).
  • onChange: يُحدّث value عند الكتابة.

2. عدة حقول

function Form() {
  const [form, setForm] = useState({
    name: "",
    email: "",
    age: 0,
  });

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value, type } = e.target;
    setForm({
      ...form,
      [name]: type === "number" ? Number(value) : value,
    });
  };

  return (
    <form>
      <input name="name" value={form.name} onChange={handleChange} />
      <input name="email" value={form.email} onChange={handleChange} />
      <input name="age" type="number" value={form.age} onChange={handleChange} />
    </form>
  );
}

النماذج (Forms)

1. النموذج البسيط

function LoginForm() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();  // منع السلوك الافتراضي
    console.log("Email:", email);
    console.log("Password:", password);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="البريد الإلكتروني"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="كلمة المرور"
      />
      <button type="submit">تسجيل الدخول</button>
    </form>
  );
}

⚠️ مهم: e.preventDefault() يمنع إعادة تحميل الصفحة.

أنواع المدخلات

1. Text

<input type="text" value={name} onChange={(e) => setName(e.target.value)} />

2. Email

<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />

3. Password

<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />

4. Number

<input type="number" value={age} onChange={(e) => setAge(Number(e.target.value))} />

5. Checkbox

<input
  type="checkbox"
  checked={isChecked}
  onChange={(e) => setIsChecked(e.target.checked)}
/>

6. Radio

<input
  type="radio"
  name="gender"
  value="male"
  checked={gender === "male"}
  onChange={(e) => setGender(e.target.value)}
/>

7. Select

<select value={country} onChange={(e) => setCountry(e.target.value)}>
  <option value="">اختر</option>
  <option value="jo">الأردن</option>
  <option value="eg">مصر</option>
  <option value="sa">السعودية</option>
</select>

8. Textarea

<textarea value={message} onChange={(e) => setMessage(e.target.value)} />

Controlled vs Uncontrolled

Controlled Components (موصى به)

const [value, setValue] = useState("");
<input value={value} onChange={(e) => setValue(e.target.value)} />

المميزات:

  • ✅ React يتحكم بالقيمة.
  • ✅ يمكن التحقق من المدخلات.
  • ✅ يمكن تصفير الحقل بسهولة.

Uncontrolled Components

const inputRef = useRef<HTMLInputElement>(null);
<input ref={inputRef} defaultValue="" />
// للقراءة: inputRef.current?.value

المميزات:

  • ✅ أبسط للحالات البسيطة.
  • ❌ لا يمكن التحقق أثناء الكتابة.

القاعدة: استخدم Controlled دائماً.

نموذج كامل: التسجيل

function RegisterForm() {
  const [form, setForm] = useState({
    name: "",
    email: "",
    password: "",
    confirmPassword: "",
    agree: false,
  });

  const [errors, setErrors] = useState<Record<string, string>>({});

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value, type, checked } = e.target;
    setForm({
      ...form,
      [name]: type === "checkbox" ? checked : value,
    });
  };

  const validate = () => {
    const newErrors: Record<string, string> = {};

    if (form.name.length < 2) {
      newErrors.name = "الاسم قصير جداً";
    }
    if (!form.email.includes("@")) {
      newErrors.email = "البريد غير صحيح";
    }
    if (form.password.length < 6) {
      newErrors.password = "كلمة المرور قصيرة";
    }
    if (form.password !== form.confirmPassword) {
      newErrors.confirmPassword = "كلمتا المرور غير متطابقتين";
    }
    if (!form.agree) {
      newErrors.agree = "يجب الموافقة على الشروط";
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (validate()) {
      alert("تم التسجيل بنجاح!");
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <input
          name="name"
          value={form.name}
          onChange={handleChange}
          placeholder="الاسم"
        />
        {errors.name && <span className="error">{errors.name}</span>}
      </div>

      <div>
        <input
          name="email"
          type="email"
          value={form.email}
          onChange={handleChange}
          placeholder="البريد الإلكتروني"
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>

      <div>
        <input
          name="password"
          type="password"
          value={form.password}
          onChange={handleChange}
          placeholder="كلمة المرور"
        />
        {errors.password && <span className="error">{errors.password}</span>}
      </div>

      <div>
        <input
          name="confirmPassword"
          type="password"
          value={form.confirmPassword}
          onChange={handleChange}
          placeholder="تأكيد كلمة المرور"
        />
        {errors.confirmPassword && (
          <span className="error">{errors.confirmPassword}</span>
        )}
      </div>

      <label>
        <input
          name="agree"
          type="checkbox"
          checked={form.agree}
          onChange={handleChange}
        />
        أوافق على الشروط
      </label>
      {errors.agree && <span className="error">{errors.agree}</span>}

      <button type="submit">تسجيل</button>
    </form>
  );
}

أحداث المفاتيح

function SearchInput() {
  const [query, setQuery] = useState("");

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter") {
      alert(`بحث عن: ${query}`);
    }
    if (e.key === "Escape") {
      setQuery("");
    }
  };

  return (
    <input
      value={query}
      onChange={(e) => setQuery(e.target.value)}
      onKeyDown={handleKeyDown}
      placeholder="ابحث واضغط Enter"
    />
  );
}

أحداث الفأرة

function HoverCard() {
  const [isHovered, setIsHovered] = useState(false);

  return (
    <div
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
      style={{
        background: isHovered ? "#3b82f6" : "#e5e7eb",
        color: isHovered ? "white" : "black",
        padding: 20,
      }}
    >
      {isHovered ? "🎉 أنت فوق البطاقة!" : "مرر الفأرة"}
    </div>
  );
}

تمارين عملية

تمرين 1: زر بسيط

أنشئ زراً يزيد عداداً عند الضغط.

الحل:

function Button() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>نقرات: {count}</button>;
}

تمرين 2: نموذج بسيط

أنشئ نموذجاً بحقل اسم وزر إرسال.

الحل:

function NameForm() {
  const [name, setName] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    alert(`مرحباً ${name}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button type="submit">إرسال</button>
    </form>
  );
}

تمرين 3: نموذج تسجيل دخول

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

الحل:

function LoginForm() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log({ email, password });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
      <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      <button type="submit">دخول</button>
    </form>
  );
}

تمرين 4: checkbox

أنشئ checkbox يعرض "مفعّل" أو "معطّل".

الحل:

function Checkbox() {
  const [checked, setChecked] = useState(false);
  return (
    <label>
      <input
        type="checkbox"
        checked={checked}
        onChange={(e) => setChecked(e.target.checked)}
      />
      {checked ? "مفعّل" : "معطّل"}
    </label>
  );
}

تمرين 5: select

أنشئ select لاختيار مدينة.

الحل:

function CitySelect() {
  const [city, setCity] = useState("");
  return (
    <div>
      <select value={city} onChange={(e) => setCity(e.target.value)}>
        <option value="">اختر مدينة</option>
        <option value="amman">عمّان</option>
        <option value="cairo">القاهرة</option>
        <option value="riyadh">الرياض</option>
      </select>
      {city && <p>اخترت: {city}</p>}
    </div>
  );
}

تمرين 6: بحث فوري

أنشئ حقل بحث يعرض النص أثناء الكتابة.

الحل:

function LiveSearch() {
  const [query, setQuery] = useState("");
  const items = ["React", "Vue", "Angular", "Svelte"];
  const filtered = items.filter((item) =>
    item.toLowerCase().includes(query.toLowerCase())
  );

  return (
    <div>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <ul>
        {filtered.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

تمرين 7: نموذج مع تحقق

أنشئ نموذجاً يتحقق من أن البريد يحتوي على @.

الحل:

function EmailForm() {
  const [email, setEmail] = useState("");
  const [error, setError] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!email.includes("@")) {
      setError("البريد غير صحيح");
      return;
    }
    alert("تم!");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={email} onChange={(e) => setEmail(e.target.value)} />
      {error && <p style={{ color: "red" }}>{error}</p>}
      <button type="submit">إرسال</button>
    </form>
  );
}

تمرين 8: نموذج تسجيل كامل

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

الحل:

function FullForm() {
  const [form, setForm] = useState({ name: "", email: "", password: "" });
  const [errors, setErrors] = useState<Record<string, string>>({});

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setForm({ ...form, [e.target.name]: e.target.value });
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const newErrors: Record<string, string> = {};
    if (form.name.length < 2) newErrors.name = "الاسم قصير";
    if (!form.email.includes("@")) newErrors.email = "البريد غير صحيح";
    if (form.password.length < 6) newErrors.password = "كلمة المرور قصيرة";
    setErrors(newErrors);

    if (Object.keys(newErrors).length === 0) {
      alert("تم بنجاح!");
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <input name="name" value={form.name} onChange={handleChange} placeholder="الاسم" />
        {errors.name && <p style={{ color: "red" }}>{errors.name}</p>}
      </div>
      <div>
        <input name="email" value={form.email} onChange={handleChange} placeholder="البريد" />
        {errors.email && <p style={{ color: "red" }}>{errors.email}</p>}
      </div>
      <div>
        <input name="password" type="password" value={form.password} onChange={handleChange} placeholder="كلمة المرور" />
        {errors.password && <p style={{ color: "red" }}>{errors.password}</p>}
      </div>
      <button type="submit">تسجيل</button>
    </form>
  );
}

حل المشاكل الشائعة

🔴 المشكلة 1: النموذج يعيد تحميل الصفحة

السبب: لم تستخدم e.preventDefault().

الحل:

const handleSubmit = (e: React.FormEvent) => {
  e.preventDefault();
  // ...
};

🔴 المشكلة 2: Cannot read property 'value' of undefined

السبب: لم تضف value أو onChange.

الحل:

<input value={value} onChange={(e) => setValue(e.target.value)} />

🔴 المشكلة 3: You provided a 'value' prop without 'onChange'

السبب: value بدون onChange (حقل للقراءة فقط).

الحل: أضف onChange أو readOnly.

🔴 المشكلة 4: A component is changing an uncontrolled input to be controlled

السبب: value يبدأ بـ undefined.

الحل:

const [value, setValue] = useState("");  // ← قيمة أولية

جدول الأحداث

الحدثالنوعالاستخدام
onClickMouseEventأزرار
onChangeChangeEventحقول الإدخال
onSubmitFormEventالنماذج
onKeyDownKeyboardEventلوحة المفاتيح
onMouseEnterMouseEventالمرور
onFocusFocusEventالتركيز
onBlurFocusEventالخروج

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

المهمةالحالة
فهم الأحداث في React⬜
استخدام onClick⬜
استخدام onChange⬜
بناء نماذج كاملة⬜
التحقق من المدخلات⬜
Controlled Components⬜
حل التمارين الثمانية⬜

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

الآن بعد أن أتقنت الأحداث والنماذج، أنت جاهز للمقال التالي:

  1. useEffect — التأثيرات الجانبية.
  2. القوائم والشروط — العرض الديناميكي.
  3. React Router — التنقل بين الصفحات.

الخلاصة

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

  • ✅ الأحداث في React (onClick, onChange, onSubmit).
  • ✅ بناء النماذج (Forms).
  • ✅ جميع أنواع المدخلات (input, select, checkbox, radio).
  • ✅ التحقق من المدخلات (Validation).
  • ✅ Controlled vs Uncontrolled Components.
  • ✅ أحداث المفاتيح والفأرة.
  • ✅ حل 8 تمارين عملية.

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

هل أتقنت الأحداث والنماذج؟ شاركنا في التعليقات!

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

React

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

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

React

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

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

React

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

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