مشروع React للمبتدئين: بناء نماذج أساسية باستخدام React Hooks

دقائق القراءة: 9

مقدمة المشروع: بناء نماذج تفاعلية باستخدام React Hooks

في هذا المشروع المخصص للمبتدئين في React، سنتعلم كيفية بناء نماذج إدخال أساسية وفعالة باستخدام React Hooks. سنغوص في مفاهيم إدارة حالة النموذج، والتعامل مع التحقق من صحة البيانات (Validation)، وكيفية معالجة طلبات الإرسال (Submit Handlers).

مثال عملي لنموذج React مع التحقق من الصحة ورسائل النجاح

ماذا سنتعلم ونبني؟

إذا كنت ترغب في تجربة الأمر بنفسك أولاً، فإليك السيناريوهات التي سنغطيها:

  • إدخال البيانات: يجب أن يتمكن المستخدم من إدخال القيم في حقول النموذج.
  • رسائل الخطأ: عند النقر على زر الإرسال ووجود حقول فارغة، يجب أن تظهر رسالة خطأ باللون الأحمر.
  • رسائل النجاح: في حال إرسال النموذج بنجاح وكانت البيانات صالحة، يجب أن تظهر رسالة نجاح.

يمكنك الحصول على الكود الأولي (Starter Code) وملفات CSS من GitHub. لنبدأ!

إدارة حالة النموذج باستخدام useState

سنبدأ بإضافة كائن حالة (state object) للاحتفاظ بقيم النموذج. في ملف App.js، داخل دالة App، أضف السطر التالي:

 const [values, setValues] = useState({
    firstName : '' ,
    lastName : '' ,
    email : '' ,
 });

لدينا ثلاثة حقول في النموذج نحتاج إلى تتبع حالتها. ستكون الحالة الأولية كائنًا يحتوي على ثلاث قيم، واحدة لكل حقل. لذا، سنسميها بأسماء مشابهة لما هي عليه في النموذج. سيتم تعيين firstName و lastName و email كقيم فارغة مبدئيًا.

ستلاحظ الآن خطأً يفيد بأن useState غير معرف. يجب استيراده من React في أعلى الملف ضمن الاستيرادات:

 import React, { useState } from "react" ;

الآن، بعد أن أصبح لدينا بعض القيم في الحالة (state)، من المنطقي تطبيقها على حقول الإدخال لدينا. أضف خاصية value لكل حقل إدخال كما يلي:

 <input id= "first-name" class = "form-field" type= "text" placeholder= "First Name" name= "firstName" value={values.firstName} />
 < input id = "last-name" class = "form-field" type = "text" placeholder = "Last Name" name = "lastName" value = {values.lastName} />
 < input id = "email" class = "form-field" type = "text" placeholder = "Email" name = "email" value = {values.email} />

كل ما فعلناه هنا هو تحديد أن قيمة حقل الإدخال ستكون مطابقة للقيمة الموجودة في الحالة. لنحفظ ونرى ما يحدث. أوه لا! إذا حاولت الكتابة في أي حقل إدخال، فلن يظهر شيء على الشاشة. ما الذي يحدث؟

تحديث حالة حقول الإدخال

لقد ذكرنا أن قيمة حقل الإدخال ستكون هي نفسها الموجودة في الحالة. على سبيل المثال، firstName مضبوط حاليًا على فارغ. لكننا لم نخبر حقل الإدخال: “في كل مرة أكتب فيها أو تتغير قيمة الإدخال، أريدك أن تقوم بتحديث الحالة بالقيم الجديدة.” عندما نفعل شيئًا كهذا، فإننا نمنح التحكم الفعال لـ React. لذلك، يجب أن نخبر React أيضًا بتحديث القيم. هذا يعني أننا يجب أن نحدث قيم الحالة في كل مرة نكتب فيها في هذه الحقول.

أبسط طريقة للقيام بذلك هي إنشاء معالج (handler) لكل حقل إدخال، يقوم بتحديث الحالة في كل مرة يحدث فيها حدث onChange. أضف الكود التالي مباشرة أسفل كائنات الحالة:

 const handleFirstNameInputChange = ( event ) => {
    event.persist();
    setValues( ( values ) => ({
        ...values,
        firstName : event.target.value,
    }));
 };

تأخذ هذه الدالة الكائن event الذي نحصل عليه من حدث onChange. نحن ببساطة نقوم بتحديث هذا الكائن ثم حفظه مرة أخرى في الحالة. سنقوم بنسخ القيم القديمة باستخدام عامل الانتشار (spread operator) الذي يمثله الثلاث نقاط (...). ثم، سنقوم بتحديث قيمة firstName لتصبح event.target.value.

نريد إضافة هذا إلى حقل الإدخال الخاص بنا. لذا، في JSX الخاص بحقل الاسم الأول، أضف الخاصية onChange كما يلي:

<input id= 'first-name' class = 'form-field' type= 'text' placeholder= 'First Name' name= 'firstName' value={values.firstName} onChange={handleFirstNameInputChange} />

الآن، إذا انتقلنا إلى المتصفح وبدأنا الكتابة، سترى أن الأمور تعمل بشكل صحيح. بقية الحقول لا تعمل بعد لأننا لم نضف معالجات لها بعد. لنلقِ نظرة على ذلك بعد قليل.

تطبيق المعالجات على بقية الحقول

لتلخيص ما يحدث: في كل مرة نكتب فيها في هذا المربع، يحدث حدث onChange لكل ضغطة مفتاح. يتم استدعاء هذا الحدث في كل مرة، ويمرر React كائن الحدث (event). نريد تحديث كائن الحالة لدينا. للقيام بذلك، نستدعي دالة setValues ونمرر كائنًا جديدًا بالقيم المحدثة.

الآن، نريد أن نفعل الشيء نفسه لـ lastName و email. أضف معالجًا آخر لكل منهما:

 const handleLastNameInputChange = ( event ) => {
    event.persist();
    setValues( ( values ) => ({
        ...values,
        lastName : event.target.value,
    }));
 };
 const handleEmailInputChange = ( event ) => {
    event.persist();
    setValues( ( values ) => ({
        ...values,
        email : event.target.value,
    }));
 };

ولا تنسَ إضافة خصائص onChange إلى حقول الإدخال لكل منها:

 <input id= "last-name" class = "form-field" type= "text" placeholder= "Last Name" name= "lastName" value={values.lastName} onChange={handleLastNameInputChange} />
 < input id = "email" class = "form-field" type = "text" placeholder = "Email" name = "email" value = {values.email} onChange = {handleEmailInputChange} />

تمام. الآن حانت لحظة الحقيقة. هل كل شيء يعمل أم أننا أفسدنا شيئًا ما على طول الطريق؟ لنحاول ونرى. املأ بعض البيانات ويجب أن تعمل حقول الإدخال الآن. رائع!

على الرغم من أن حقول الإدخال تعمل، لا يزال لدينا مشكلة غريبة: إذا كتبنا شيئًا في النموذج وحاولنا الإرسال، فلن يحدث شيء. ستتم إعادة تحميل الصفحة وستفقد جميع بيانات النموذج. دعنا نفعل شيئًا حيال ذلك.

عرض رسالة النجاح بعد الإرسال

بعد النقر على زر التسجيل، يجب أن تظهر رسالة نجاح إذا كان النموذج صالحًا. ما نريده هو الانتقال إلى JSX الخاص بنا، وإضافة عنصر div جديد أسفل النموذج مباشرة. لقد أضفت الفئات (classes) اللازمة لرسالة النجاح:

<div class = 'success-message' >Success! Thank you for registering</div>

بالطبع، هذا مجرد مثال توضيحي ولا يتصل بخادم حقيقي. نحن فقط نعرض رسالة للمستخدم. ولكن حاليًا، تظهر هذه الرسالة طوال الوقت. ما نريده هو أن تظهر فقط إذا قام المستخدم بإرسال النموذج بنجاح. لذلك، سنضيف كائن حالة آخر كما يلي:

 const [submitted, setSubmitted] = useState( false );

سنبقي هذه الحالة منفصلة عن قيم النموذج الأخرى لتجنب إعادة الرندر (re-render) غير الضرورية. ستخبرنا هذه الحالة ما إذا كان النموذج قد تم إرساله أم لا. سيتم تعيينها مبدئيًا على false لأن النموذج لن يكون قد تم إرساله عند تحميل الصفحة لأول مرة.

الآن، سنقوم ببعض التعديلات الذكية في JSX لكي نقول: “إذا كانت submitted صحيحة، فإننا نريد عرض رسالة النجاح.” قم بتحديث السطر الذي أضفناه للتو بما يلي:

{submitted && < div class = 'success-message' > Success! Thank you for registering </ div > }

سنقوم بتغليف رسالة النجاح الخاصة بنا داخل عامل تشغيل ثلاثي (ternary operator). هذا أساسًا عبارة if مختصرة تسمح لنا بعرض العناصر ديناميكيًا على الصفحة. ستظهر رسالة النجاح الآن فقط إذا كانت submitted صحيحة.

كما ترون الآن في المتصفح، اختفت الرسالة. إذا عدنا إلى كائن الحالة submitted وغيرنا قيمته إلى true، فيجب أن تظهر مرة أخرى. وبالفعل تظهر! سنعيدها إلى false ثم نحدث المتصفح لنرى ما يحدث.

لم نخبر زر التسجيل أو النموذج بما يحدث عند الإرسال، لذلك ستستمر الصفحة في إعادة التحميل. نحتاج الآن إلى معالج جديد للتعامل مع النقر على زر التسجيل. أضف الكود التالي إلى معالجات الأحداث لدينا:

 const handleSubmit = ( e ) => {
    e.preventDefault();
    setSubmitted( true );
 };

الدالة e.preventDefault() ستوقف إعادة التحميل التي كنا نراها. سنضيف المزيد من المنطق هنا لاحقًا حول التحقق من الصحة وما إلى ذلك. ولكن في الوقت الحالي، سنقوم فقط بتعيين setSubmitted إلى true.

بعد ذلك، نحتاج إلى إخبار النموذج باستدعاء هذه الدالة عند إرساله. قم بتحديث JSX لتضمين خاصية onSubmit في وسم form كما يلي:

<form class = 'register-form' onSubmit={handleSubmit}>
 //... other code
 </form>

الآن إذا قمنا بتشغيل الكود في المتصفح، ونقرنا على زر التسجيل، ستظهر الرسالة. رائع!

إضافة التحقق من الصحة وعرض رسائل الخطأ

يبدو نموذجنا جيدًا حتى الآن، لكننا نفتقد مكونًا رئيسيًا لأي نموذج، وهو التحقق من صحة البيانات (Validation). إذا نظرنا إلى مثالنا العملي، إذا قمت بإرسال النموذج مع أي حقول فارغة، فستظهر رسالة خطأ تقول: “الرجاء إدخال تفاصيلك.”

أسفل كل حقل إدخال، سنضيف وسم <span> سيحتوي على رسالة الخطأ. يجب أن يبدو JSX الخاص بك مشابهًا لهذا:

 <input id= "first-name" class = "form-field" type= "text" disabled={submitted} placeholder= "First Name" name= "firstName" value={values.firstName} onChange={handleFirstNameInputChange} />
 {submitted && !values.firstName && < span id = 'first-name-error' > Please enter a first name </ span > }
 < input id = "last-name" class = "form-field" type = "text" placeholder = "Last Name" name = "lastName" value = {values.lastName} onChange = {handleLastNameInputChange} />
 {submitted && !values.lastName && < span id = 'last-name-error' > Please enter a last name </ span > }
 < input id = "email" class = "form-field" type = "text" placeholder = "Email" name = "email" value = {values.email} onChange = {handleEmailInputChange} />
 {submitted && !values.email && < span id = 'email-error' > Please enter an email address </ span > }

ما نقوم به هنا هو التحقق مما إذا كان النموذج قد تم إرساله (submitted)، وما إذا كان كائن الحالة الخاص بـ firstName فارغًا (!values.firstName). إذا كان الأمر كذلك، فإننا نريد عرض رسالة الخطأ. مرة أخرى، نحن نستخدم عامل التشغيل الثلاثي (ternary operator)، لا شيء معقد!

الآن، نريد التأكد من أن رسالة النجاح هذه تظهر فقط إذا كان النموذج صالحًا. أضف قيمة حالة جديدة:

 const [valid, setValid] = useState( false );

تُستخدم هذه الحالة لإخبارنا ما إذا كان نموذجنا صالحًا. تذكر أن استخدام كائنات الحالة (state objects) طريقة جيدة للاحتفاظ بـ “حالة” الأجزاء المختلفة من تطبيقك. يجب أن تظهر رسائل النجاح فقط إذا كانت submitted صحيحة و valid صحيحة أيضًا.

بما أننا قمنا بتعيين valid كـ false مبدئيًا، فلن تظهر رسالة النجاح. في دالة handleSubmit الخاصة بنا، نريد أن نقول إن valid صحيحة إذا كان النموذج صالحًا. يمكننا القيام بذلك عن طريق التحقق من كل قيمة من قيم الحالة لحقول النموذج، والتأكد من أنها قيمة حقيقية (truthy value). أضف ما يلي:

 const handleSubmit = ( event ) => {
    event.preventDefault();
    if (values.firstName && values.lastName && values.email) {
        setValid( true );
    }
    setSubmitted( true );
 }

إذا كانت أي من هذه الحقول فارغة (أو قيمتها false)، فستبقى valid كـ false. هذا يعني أن رسالة النجاح لن تظهر.

اختبار التحقق من الصحة

دعنا نرى ذلك يعمل. إذا نقرنا على زر التسجيل بدون ملء الحقول، ستظهر رسائل الخطأ لدينا. لنكتب بعض البيانات الصالحة، ونضغط على تسجيل، وستظهر رسالة النجاح! رائع!

الخلاصة التقنية

لقد قمنا في هذا المقال بتغطية الجوانب الأساسية لبناء نماذج React تفاعلية باستخدام React Hooks. من خلال استخدام useState، تمكنا من إدارة حالة حقول الإدخال، وعرض رسائل النجاح، وتطبيق منطق التحقق من الصحة لضمان جودة البيانات المدخلة. هذه التقنيات ضرورية لأي مطور React يسعى لبناء واجهات مستخدم قوية وتفاعلية. إن فهم كيفية عمل Hooks في إدارة الحالة والأحداث يفتح الباب أمام تطوير تطبيقات أكثر تعقيدًا وكفاءة.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *