دورة TanStack Form الكاملة › دورة TanStack Form الكاملة 1 / 1 السابق التالي

النموذج الأول (First Form)

الدرس 3 من 21 · دورة TanStack Form الكاملة · 10 دقيقة و26 ثانية

الفيديو الأصلي باللغة الإنجليزية. إذا تعذّر تشغيله هنا، شاهده على موقع المؤلف. التفريغ النصي العربي الكامل أدناه.

مستودع شيفرة هذا الدرس

الفرع: first-form

[00:01] لنفترض الآن أنّه لدينا نموذج تسجيل (register form) مثلاً نحتاج إلى إنشائه.

[00:05] إذًا أولًا سأذهب إلى هنا، في مجلد lib هذا ربما أو ما شابه، كي أنشئ مكوّنًا (component) جديدًا. إذًا في هنا سأنشئ مكوّنًا. فلنسمّه RegisterForm.tsx.

[00:17] والآن أولًا سأنشئ هنا واجهة (interface) بـ TypeScript ستضم كل ما سيحويه نموذجنا. فلنفترض أنّ نموذجنا سيتضمن. لدينا هنا واجهة RegisterForm. سنمتلك

[00:29] الاسم الأول، والاسم الأخير، والعمر، والبريد الإلكتروني، وكلمة السر، وتأكيد كلمة السر. وبالإضافة إلى ذلك ستتوفّر لدينا أمور متشعّبة (nested) أيضًا. إذًا سنمتلك عنوانًا (address). العنوان كائن (object) وداخله حقول (fields)

[00:44] متشعّبة مثل street، وcity، وstate وما إلى ذلك. ولدينا أيضًا مصفوفة (array) مثلاً. إذًا لدينا مصفوفة مهارات (skills) وهي مصفوفة من الكائنات حيث يتضمن كل كائن في هذه المصفوفة name، وID، ومستوى خبرة — مبتدئ (beginner)،

[00:58] ووسيط (intermediate)، وخبير (expert)، ويمكن أن نمتلك قيمة منطقية (boolean) أيضًا. إذًا لدينا هنا حقل acceptTerms. ففي هنا يكون لدينا تقريبًا جميع الأنواع (types) الممكنة التي يمكن أن تكون في نموذج.

[01:10] إذًا سيكون هذا مثالًا جيدًا. لكن الآن لننشئ مكوّننا. سأنشئ هنا مكوّنًا RegisterForm. ومن هنا سنعيد بعض الترميز (markup). إذًا من أجل استخدام TanStack Form نستخدم أولًا الخُطّاف (hook)

[01:25] useForm. إذًا في هنا سأعرّف نموذجًا جديدًا وسأستورد (import) useForm من TanStack Form، وفي هنا نحتاج إلى تحديد قيمنا الافتراضية (default values). فنستطيع تحديد القيم الافتراضية هنا.

[01:39] ولنقل أنّه في البداية سنمتلك نموذجًا فارغًا. إذًا في هنا سأعرّف هذا الثابت (constant) defaultValues الذي له نوع RegisterForm. ثم سأقوم فقط بتحديد بعض القيم الفارغة هنا. إذًا في هنا يمكننا

[01:52] تمرير هذا ببساطة إلى الخُطّاف useForm لدينا.

[01:56] يمكنك رغم ذلك — ربما أن يكون لديك نموذج تعديل (edit form) سنكون فيه بعض الحقول معبّأة. ما يمكنك فعله هو أنك تستطيع تعبئة قيم النموذج بشيء ربما حمّلته من واجهة برمجية (API) أو من قاعدة بيانات وما إلى ذلك. ويمكنك فعل ذلك

[02:08] ببساطة — لدينا هنا مثال حيث تضيف في القيم الافتراضية لديك بعض البيانات من حالة (state) ما. إذًا في هنا مثلاً لدينا مثال يستخدم الخُطّاف useQuery من TanStack Query حيث نحمّل بعض البيانات من قاعدة بيانات ربما، و

[02:24] نحصل على بياناتنا ونضع بياناتنا هنا في قيمنا الافتراضية بدلًا من الحقول الفارغة فقط التي لدينا هنا، وكذلك لا نصيّر (render) نموذجنا إلا عندما ينتهي تحميلنا أيضًا. لكن في حالتنا، فلنحافظ ربما على البساطة ونستخدم

[02:39] نموذجنا الفارغ الآن. لكن الآن بعد أن أصبح لدينا هذا النموذج، سنكون قادرين على تصيير حقولنا باستخدام بعض المكوّنات داخل هذا النموذج. إذًا في هنا، فلنشئ أولًا عنصر form. وسنتعامل مع الإرسال (submission) ربما

[02:54] لاحقًا، لكن فلنمتلك مجرد عنصر form. وفي هنا نحتاج إلى تصيير حقولنا.

[02:58] إذًا ما يمكننا فعله هو أننا نستطيع استخدام form.Field. وفي هنا سيتعين علينا أن نمنحه اسمًا (name)، ويجب أن يكون هذا الاسم أحد حقولنا، فسنحصل هنا على إكمالات TypeScript وأمان أنواع (type safety) للحقول الممكنة لدينا التي حدّدناها

[03:12] في نوعنا. في حالتنا، فلنقل ربما — لنقل أنّنا نحتاج إلى تصيير الاسم الأول لدينا كأبناء (children) أو كابن (child) إلى form.Field. ويمكننا تمرير دالة، وفي هذه الدالة سيتوفّر لنا الوصول إلى كائن

[03:27] الحقل هذا. سنطّلع على ذلك بعد قليل. إذًا في هنا يمكننا أن نعيد شيئًا ما. فلنعيد ربما لا شيء الآن، ولنطبع ربما هذا الحقل عبر console.log لنرَ ما سيكون داخل منه. و

[03:42] كذلك ونحن هنا، فلنطبع أيضًا نموذجنا عبر console.log لنتأمل ما ستتوفّر به لنا في هذا النموذج. إذًا بحفظ هذا، فلنفتح فحص الصفحة (inspect) هنا ونلقي نظرة على console لدينا.

[03:56] وبالطبع — عذرًا — نحتاج في app.tsx لدينا، نحتاج إلى تصيير نموذجنا. فلنستورد RegisterForm من مجلد lib لدينا هكذا.

[04:06] إذًا لدينا واجهة برمجية للنموذج (form API) وواجهة برمجية للحقل (field API). form API يأتي بالطبع من هنا، و field API يأتي من هنا. في form API لدينا بعض الأشياء المتعلقة بالنموذج بأكمله. لن نتناول التفاصيل الآن،

[04:23] غير أنّ هذه بعض الواجهات البرمجية المتعلقة بنموذجنا بأكمله لا بحقل معيّن فقط.

[04:29] ثم في field API لدينا أشياء متعلقة بحقلنا المعيّن. فتتوفّر لدينا أشياء أمثال getValue، وgetMeta. ويتوفّر عندنا أيضًا اسم حقلنا، وكما ترى هنا: firstName. وينبغي أن يتوفّر لدينا هنا أيضًا حالة (state) لحقلنا وهي

[04:44] ستضم كل ما يتعلق بحقلنا: أخطاء (errors)، والقيمة، وهل حقلنا قد تعرّض للتغيير (dirty)، وما إلى ذلك. سنرى كل شيء بالتفصيل — هذه مجرد نظرة سريعة — لكن الآن لنُبطل هذه الطباعات (logs) ولنستخدم حقًا

[04:59] شيئًا من form API الذي رأيناه، وهو دالة ستتولى معالجة الإرسال. إذًا في هنا — onSubmit — سنحتاج إلى تمرير دالة هنا، وسنحتاج في هنا إلى منع الإرسال

[05:11] الافتراضي ونُدع TanStack Form يتولّى الإرسال عن طريق استدعاء دالة داخل هذا form API. إذًا في هنا ضمن form لدينا handleSubmit نستطيع استدعاءه، وسيتولّى هذا معالجة الإرسال والتحقق من الصحة (validation) وما إلى ذلك. سنرى

[05:26] مزيدًا من التفاصيل بعد قليل.

[05:29] لكن قبل إرسال نموذجنا، يلزمني أن أذكر شيئًا سريعًا هنا. إذًا عندما نمرّر هذه القيم الافتراضية، يمكننا تمريرها هكذا، وهذا مقبول تمامًا.

[05:38] غير أنّه يمكننا أيضًا استخدام دالة تُدعى formOptions حيث نستطيع تعريف خيارات نموذج (form options) يمكن مشاركتها عبر نماذج متعددة. إذًا في هنا مثلاً يمكن أن يكون لدينا ثابت فلنسمّه formOptions. ومن هنا يمكننا استدعاء

[05:52] دالة تُدعى formOptions من TanStack Form، وفي هنا يمكننا تمرير بعض خيارات النموذج مثل التحقق من الصحة — عذرًا — مثل القيم الافتراضية — عذرًا — فلنسمّ هذا ربما شيئًا آخر. الآن وبوجود هذا يمكننا ربما تصديره (export) و

[06:08] استخدامه عبر عدّة نماذج. كيف؟ ببساطة: في هنا، بدلًا من تعريف القيم الافتراضية، نستطيع نشر (spread) كل ما لدينا في formOptions هكذا، وسنحصل على النتيجة نفسها تمامًا. إذًا الآن بالنسبة إلى هذا النموذج المعيّن يمكننا

[06:21] إعادة استخدام هذه الخيارات، ثم يمكننا ربما أن نضيف خيارات خاصة لهذا النموذج أيضًا. حسنًا. إذًا فلنمرّر الآن الخيار الأول الذي يلزمنا تمريره، وهو onSubmit، وهذه ستكون هي الدالة المسؤولة عن معالجة

[06:35] إرسال نموذجك. فعندما نرسل نموذجنا ستُنفَّذ هذه الدالة وستتوفّر لنا بعض الأشياء هنا. فلنسمّها ربما data، ولنطبعها عبر console.log.

[06:48] إذًا فلنطبع data عبر console.log. والآن فلنرسل نموذجنا عبر — ربما نضيف هنا زرًا سريعًا: Submit، ونمنحه أيضًا type بقيمة submit. أصبح لدينا الآن زر الإرسال (submit button) هذا. وعندما ننقر عليه — تذكّر أنه كلما أرسلنا

[07:04] نموذجنا، فنحن نستدعي في الواقع form.handleSubmit الذي سيستدعي هذه الدالة التي نمرّرها هنا في useForm. فلننقر عليه إذًا وستتوفّر لنا بعض الأشياء، بما فيها قيمتنا، أي قيمة

[07:17] نموذجنا. بالطبع لم نغيّر شيئًا في حقولنا، لذا نحصل هنا على قيمنا الافتراضية. فمن هذه الدالة نستطيع الحصول على قيمتنا وربما أن نفعل بها شيئًا، كأن نرسل الطلب (request) إلى واجهة برمجية (API) ما وما إلى ذلك. لكن الآن

[07:33] فلنعرض حقولنا أخيرًا. تذكّر أنّه في هنا لدينا هذا form.Field وأنّنا كنّا نعيد هنا مجرد لا شيء. فلنعيد الآن بعض input للتعامل مع الاسم الأول. سأستخدم أولًا مجرد حقل input عادي من HTML

[07:47] ثم لاحقًا سنستخدم مكوّنات من shadcn أيضًا. غير أنّه فلنضيف الآن فقط بعض div غلاف (wrapper) هنا مع هامش سفلي (margin bottom)، ثم فلنضيف حقل input لدينا. عذرًا. في حقل input لدينا يلزمنا تمرير بعض

[08:03] الأشياء من هذا الحقل الذي نحصل عليه هنا.

[08:05] أولًا سأضيف فقط بعض التنسيق (styling)، فيصبح الأمر هكذا. كذلك فلنجعله — فلنضف بعض الأصناف (classes) إلى div هذا كي يبدو أصغر قليلاً. ها هو. إذًا ما الذي يتعين علينا فعله هنا؟ نحن

[08:22] نحتاج إلى تمرير قيمة حقلنا، وهي التي نحصل عليها من حقلنا. ثم داخل state نحصل على قيمتنا.

[08:33] والآن يلزمنا، كلّما حدّثنا حقل input لدينا، أن نحدّث قيمة هذا الحقل، ويمكننا فعل ذلك بتمرير دالة onChange هنا. وفي onChange يجب أن نحصل على قيمتنا، وهي التي نحصل عليها من event لدينا، ثم أن نستدعي دالة

[08:47] موجودة أيضًا في حقلنا، وهي handleChange. إذًا handleChange، ويلزمنا تمرير القيمة التي هي event.target.value.

[09:02] وأخيرًا نحتاج أيضًا إلى إضافة دالة onBlur واستدعاء دالة من حقلنا ستتولى معالجة التركيز (blur)، لأنّه عند التركيز يمكننا إجراء بعض التحقق من الصحة أيضًا، ونحتاج إلى أن يتولّى TanStack Form ذلك. إذًا نحتاج إلى استدعاء

[09:11] دالة من field وهي handleBlur هكذا.

[09:17] وهذا ينبغي أن يكون تقريبًا كل ما يلزمنا تمريره إلى حقل input لدينا من الحقل الذي نحصل عليه من هنا.

[09:24] فلنضيف أيضًا ربما placeholder هنا: First name. والآن فلنجري ربما تحديثًا (refresh). والآن عندما نكتب شيئًا هنا ينبغي أن يحدّث ذلك نموذجنا. كيف نعرف ذلك؟ بالطبع يمكننا أن نتأكد ربما بإلقاء نظرة على

[09:40] طباعات console لدينا، وننقر على الإرسال (submit).

[09:43] والآن — تذكّر أنّنا في هنا نطبع قيمة نموذجنا. إذًا في هنا نحصل على قيمة الاسم الأول الذي كتبناه.

[09:52] يمكننا أيضًا استخدام أدوات التطوير (dev tools) هذه.

[09:55] غير أنّه ما دمتُ أسجّل هذا، فإنّ أدوات التطوير هذه بها بعض الأخطاء، فأحيانًا قد لا تعرض النموذج هنا. وعمومًا لدينا — يمكننا النقر على TanStack Form. سيكون لديك نموذج هنا، وفي هنا ستتوفّر لك

[10:10] معلومات عن نموذجك، وكما ترى لدينا قيمة الاسم الأول لدينا، ويتوفّر لدينا أيضًا بعض المعلومات الوصفية (meta). ستضم معلومات عن حقولنا، عما إذا كانت بها أخطاء وما إلى ذلك، وهذا ما

[10:24] سنناقشه في التالي. دعنا الآن