الأحداث والنماذج في React — دليل شامل 2026
دليل عملي مفصل للأحداث (Events) والنماذج (Forms) في React — onClick, onChange, onSubmit، مع تمارين وحلول
في المقال السابق، تعلمت State وكيفية إدارة البيانات المتغيرة. الآن سنتعلم الأحداث (Events) و النماذج (Forms) — وهي الطريقة التي يتفاعل بها المستخدم مع تطبيقك.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم الأحداث والنماذج في React، مع تمارين وحلول.
ما هي الأحداث؟
الأحداث (Events) هي تفاعلات المستخدم مع الصفحة:
- النقر (click).
- الكتابة (input).
- الإرسال (submit).
- المرور (mouseover).
- الضغط على المفاتيح (keydown).
الفرق بين HTML و React:
| HTML | React |
|---|---|
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(""); // ← قيمة أولية
جدول الأحداث
| الحدث | النوع | الاستخدام |
|---|---|---|
onClick | MouseEvent | أزرار |
onChange | ChangeEvent | حقول الإدخال |
onSubmit | FormEvent | النماذج |
onKeyDown | KeyboardEvent | لوحة المفاتيح |
onMouseEnter | MouseEvent | المرور |
onFocus | FocusEvent | التركيز |
onBlur | FocusEvent | الخروج |
قائمة تحقق نهائية
| المهمة | الحالة |
|---|---|
| فهم الأحداث في React | ⬜ |
| استخدام onClick | ⬜ |
| استخدام onChange | ⬜ |
| بناء نماذج كاملة | ⬜ |
| التحقق من المدخلات | ⬜ |
| Controlled Components | ⬜ |
| حل التمارين الثمانية | ⬜ |
ماذا بعد هذا المقال؟
الآن بعد أن أتقنت الأحداث والنماذج، أنت جاهز للمقال التالي:
- useEffect — التأثيرات الجانبية.
- القوائم والشروط — العرض الديناميكي.
- React Router — التنقل بين الصفحات.
الخلاصة
في هذا المقال، تعلمت:
- ✅ الأحداث في React (onClick, onChange, onSubmit).
- ✅ بناء النماذج (Forms).
- ✅ جميع أنواع المدخلات (input, select, checkbox, radio).
- ✅ التحقق من المدخلات (Validation).
- ✅ Controlled vs Uncontrolled Components.
- ✅ أحداث المفاتيح والفأرة.
- ✅ حل 8 تمارين عملية.
تذكر: الأحداث والنماذج هي ما يجعل التطبيق تفاعلياً. أتقنها جيداً.
هل أتقنت الأحداث والنماذج؟ شاركنا في التعليقات!
State في React — دليل شامل useState 2026
useEffect في React — دليل شامل للتأثيرات الجانبية 2026
📚 مقالات ذات صلة
مشروع React متكامل — تطبيق متجر إلكتروني 2026
مشروع عملي شامل لبناء تطبيق متجر إلكتروني بـ React و TypeScript — مع السلة، البحث، التصفية، والحفظ التلقائي
Context API في React — إدارة الحالة العامة 2026
دليل عملي مفصل لـ Context API في React — إنشاء Context، Provider، useContext، مع تمارين وحلول
React Router — التنقل بين الصفحات في React 2026
دليل عملي مفصل لـ React Router — التنقل، المسارات، الروابط، والمعاملات، مع تمارين وحلول