إنشاء نماذج رد فعل في 2020

مرحباً هابر. أقدم لكم ترجمة المقال "إنشاء النماذج في رد فعل في عام 2020" من قبل كريستوفر سيلبيك

صورة


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

تعد معالجة النماذج جزءًا لا يتجزأ من عدد كبير من تطبيقات الويب ، وهذا أحد الأشياء التي يعملها React بشكل أفضل. لديك حرية كبيرة في إنشاء ومعالجة النماذج. ولكن هل هناك طريقة أفضل للقيام بذلك؟

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

تذكر قواعد الشكل الجيد


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

معالجة النماذج باستخدام هوك الدولة


للبدء ، دعنا نرى كيف أعمل عادةً مع حالة النموذج. أقوم بحفظ جميع الحقول كعناصر حالة منفصلة وأقوم بتحديثها بشكل منفصل ، وهو ما يبدو كالتالي:

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

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    api.login(email, password);
  };
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor='email'>Email</label>
        <input type='email' id='email' value={email} onChange={(e) => setEmail(e.target.value)} />
      </div>
      <div>
        <label htmlFor='password'>Password</label>
        <input type='password' id='password' value={password} onChange={(e) => setPassword(e.target.value)} />
      </div>
    </form>
  );
}

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

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

إنشاء خطاف مخصص


دعونا نجري القليل من إعادة الهيكلة وإنشاء خطاف خاص بنا ، مما سيحسن قليلاً من التعليمات البرمجية الخاصة بنا:

const useFormField = (initialValue: string = '') => {
  const [value, setValue] = React.useState(initialValue);
  const onChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value), []);
  return { value, onChange };
};

export function LoginForm() {
  const emailField = useFormField();
  const passwordField = useFormField();

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    api.login(emailField.value, passwordField.value);
  };
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor='email'>Email</label>
        <input type='email' id='email' {...emailField} />
      </div>
      <div>
        <label htmlFor='password'>Password</label>
        <input type='password' id='password' {...passwordField} />
      </div>
    </form>
  );
}

نقوم بإنشاء خطاف استخدام useFormField مخصص ينشئ معالج حدث onChange لنا ، كما يخزن القيمة في حالة النموذج. في هذه الحالة ، يمكننا استخدام خطافتنا مع جميع حقول النموذج.

معالجة عدد كبير من المجالات


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

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

export function LoginForm() {
  const { formFields, createChangeHandler } = useFormFields({
    email: '',
    password: '',
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    api.login(formFields.email, formFields.password);
  };
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor='email'>Email</label>
        <input type='email' id='email' value={formFields.email} onChange={createChangeHandler('email')} />
      </div>
      <div>
        <label htmlFor='password'>Password</label>
        <input type='password' id='password' value={formFields.password} onChange={createChangeHandler('password')} />
      </div>
    </form>
  );
}

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

طريقه بديله


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

هذا هو نفس النموذج ، ولكن السماح للمتصفح بمعالجة حالة النموذج:

export function LoginForm() {
  const handleSubmit = (e: React.FormEvent) => {
	e.preventDefault();
	const formData = new FormData(e.target as HTMLFormElement);
	api.login(formData.get('email'), formData.get('password'));
  };
  return (
	<form onSubmit={handleSubmit}>
  	<div>
    	<label htmlFor="email">Email</label>
    	<input
      	type="email"
      	id="email"
      	name="email"
    	/>
  	</div>
  	<div>
    	<label htmlFor="password">Password</label>
    	<input
      	type="password"
      	id="password"
      	name="password"
    	/>
  	</div>
  	<button>Log in</button>
	</form>
  );
}

انظروا كم هو سهل! لم يتم استخدام خطاف واحد ، ولا يوجد إعداد للقيمة الأولية ، ولا يوجد معالج onChange. أفضل جزء هو أن الرمز لا يزال يعمل كما كان من قبل - ولكن كيف؟

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

نحصل على رابط للنموذج في DOM من خلال السمة الهدف لحدث الإرسال وننشئ نسخة جديدة من فئة FormData. الآن يمكننا الحصول على جميع الحقول من خلال سمة اسمها عن طريق استدعاء formData.get ("اسم حقل الإدخال").

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

متى تستخدم كل طريقة


نظرًا لأن النماذج جزء لا يتجزأ من معظم تطبيقات الويب ، فمن المهم معرفة كيفية التعامل معها. و React يوفر لك العديد من الطرق للقيام بذلك.
بالنسبة للنماذج البسيطة التي لا تتطلب التحقق من صحة صارمة (أو التي يمكن أن تعتمد على عناصر التحكم في التحقق من صحة نموذج HTML5 ) ، أقترح عليك ببساطة استخدام معالجة الحالة المضمنة التي يوفرها لنا DOM بشكل افتراضي. هناك عدد غير قليل من الأشياء التي لا يمكنك القيام بها (على سبيل المثال ، تغيير قيم الإدخال برمجيًا أو التحقق في الوقت الحقيقي) ، ولكن في أبسط الحالات (على سبيل المثال ، حقل بحث أو حقل تسجيل دخول ، كما هو موضح أعلاه) ، ربما ستجده مناسبًا نهجنا البديل باستخدام واجهة برمجة تطبيقات المتصفح.

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

تجدر الإشارة إلى أن مطوري React يوصون باستخدام مكونات خاضعة للرقابة (يعالجون صراحة حالة المكون) في معظم الحالات - حيث يمنحك هذا النهج مزيدًا من المرونة في المستقبل. في رأيي ، غالبًا ما يضحي المطورون بالبساطة من أجل المرونة ، والتي لا يحتاجونها غالبًا.

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

All Articles