رد فعل البرنامج التعليمي الجزء 25: ورشة عمل على النماذج

في جزء اليوم من ترجمة دورة التدريب React ، فأنت مدعو لإكمال مهمة النموذج.

صورة

الجزء 1: نظرة عامة على الدورة ، وأسباب شعبية React ، ReactDOM و JSX
الجزء 2: المكونات الوظيفية
الجزء 3: ملفات المكونات ، هيكل المشروع
الجزء 4: مكونات الوالدين والطفل
الجزء 5: بدء العمل في تطبيق TODO ، أساسيات التصميم
الجزء 6: حول بعض ميزات الدورة ، JSX وجافا سكريبت
الجزء 7: الأنماط المضمنة
الجزء 8: مواصلة العمل على تطبيق TODO ، الإلمام بخصائص المكونات
الجزء 9: خصائص المكون
الجزء 10: ورشة عمل حول العمل مع خصائص المكون والتصميم
الجزء 11: توليد العلامات الديناميكية وطريقة صفائف الخريطة
الجزء 12: ورشة العمل ، المرحلة الثالثة من العمل على طلب TODO
الجزء 13: المكونات القائمة على الفصل
الجزء 14: ورشة عمل حول المكونات القائمة على الفصل ، وحالة المكون
الجزء 15: ورش العمل الصحية المكونة
الجزء 16: المرحلة الرابعة من العمل على طلب TODO ، التعامل مع الأحداث
الجزء 17: المرحلة الخامسة من العمل على تطبيق TODO ، وتعديل حالة المكونات
الجزء 18: المرحلة السادسة من العمل على طلب TODO
الجزء 19: طرق دورة حياة المكون
الجزء 20: الدرس الأول في التقديم الشرطي
الجزء 21: الدرس الثاني وورشة العمل حول التقديم الشرطي
الجزء 22: المرحلة السابعة من العمل على تطبيق TODO ، وتنزيل البيانات من مصادر خارجية
الجزء 23: الدرس الأول حول العمل مع النماذج
الجزء 24: نماذج الدرس الثاني
الجزء 25: ورشة عمل حول العمل مع النماذج
الجزء 26: بنية التطبيق ، نمط الحاوية / المكون
الجزء 27: مشروع المقرر

الدرس 43. ورشة العمل. العمل مع النماذج


الأصل

▍Zadanie


في هذا الدرس العملي ، تتم دعوتك لإحضار رمز مكون App ، الموجود في ملف App.js الخاص بالمشروع القياسي الذي تم إنشاؤه بواسطة create-react-app. هنا هو الكود:

 import React, {Component} from "react" class App extends Component {   constructor() {       super()       this.state = {}   }     render() {       return (           <main>               <form>                   <input placeholder="First Name" /><br />                   <input placeholder="Last Name" /><br />                   <input placeholder="Age" /><br />                                     {/*       */}                   <br />                                     {/*          */}                   <br />                                     {/*        */}                   <br />                                     <button>Submit</button>               </form>               <hr />               <h2><font color="#3AC1EF">Entered information:</font></h2>               <p>Your name: {/*    */}</p>               <p>Your age: {/*  */}</p>               <p>Your gender: {/*  */}</p>               <p>Your destination: {/*   */}</p>               <p>                   Your dietary restrictions:                   {/*    */}               </p>           </main>       )   } } export default App 

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

إليك ما يعرضه المكون الآن على الشاشة.


تطبيق في المتصفح

▍Reshenie


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

في الوقت الحالي ، ستبدو حالة المكون كما هو موضح أدناه.

 this.state = {   firstName: "",   lastName: "",   age: 0,   gender: "",   destination: "",   dietaryRestrictions: [] } 

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

الآن ، بعد تهيئة الحالة ، دعنا نعتني بإعداد الضوابط. نظرًا لأن الكود يحتوي بالفعل على وصف لحقول الإدخال - فلنبدأ بها.

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

 <input   name="firstName"   value={this.state.firstName}   onChange={this.handleChange}   placeholder="First Name" /> <br /> <input   name="lastName"   value={this.state.lastName}   onChange={this.handleChange}   placeholder="Last Name" /> <br /> <input   name="age"   value={this.state.age}   onChange={this.handleChange}   placeholder="Age" /> 

كطريقة تستخدم لمعالجة أحداث onChange في هذه الحقول ، لا يزال this.handleChange غير موجود. قم بإنشاء هذه الطريقة:

 handleChange(event) {   const {name, value} = event.target   this.setState({       [name]: value   }) } 

نحن هنا نستخرج خصائص name value من كائن event.target ، ثم نستخدمها لتعيين خاصية الحالة المقابلة. في الوقت الحالي ، سوف تلائمنا شفرة معالج الأحداث العالمية هذه ، لكن في وقت لاحق ، عندما نبدأ العمل مع الأعلام ، سنقوم بإجراء تغييرات عليها.

لا تنسى this الرابط المنجز في مُنشئ المكون:

 this.handleChange = this.handleChange.bind(this) 

من أجل تحقيق الإخراج في أسفل صفحة البيانات المدخلة في firstName secondName age ، سنعمل مع عناصر <p> المقابلة ، secondName إلى النموذج التالي:

 <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> 

الآن دعونا نلقي نظرة على ما حصلنا عليه.


تطبيق في المتصفح

كما ترون ، في الحقل الخاص بإدخال العمر ، لا يتم عرض تلميح. بدلاً من ذلك ، يتم عرض ما تم تعيينه في خاصية الحالة age ، أي 0. نحتاج إلى تلميح في الحقل الفارغ. دعنا نحاول استبدال قيمة age في الولاية بالقيمة null . بعد ذلك ، اتضح أن النموذج يبدو كما يجب ، ولكن يتم عرض التحذير التالي في وحدة التحكم فيما يتعلق بحقل age :

 Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components 

نتيجةً لذلك ، سنحتاج إلى استبدال قيمة خاصية الحالة age بسلسلة فارغة ، وبذلك يتم إدخال رمز تهيئة الحالة إلى النموذج التالي:

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   dietaryRestrictions: [] } 

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


تطبيق في المتصفح

كما ترون ، في هذه المرحلة من العمل ، كل شيء يعمل كما هو متوقع.

الآن سوف نشارك في عناصر جديدة. ستكون الخطوة التالية في العمل على النموذج إضافة مفاتيح إليه.

نلف المفاتيح في <label> ، والتي لن تسمح لنا فقط بتوقيع رمز التبديل ، ولكن أيضًا للتأكد من أن النقر فوق هذا التوقيع ، أي العنصر الأصلي ، يؤدي إلى تحديده.

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

نتيجة لذلك ، سيبدو رمز وصف المحول كما يلي:

 <label>   <input       type="radio"       name="gender"       value="male"       checked={this.state.gender === "male"}       onChange={this.handleChange}   /> Male </label> <br /> <label>   <input       type="radio"       name="gender"       value="female"       checked={this.state.gender === "female"}       onChange={this.handleChange}   /> Female </label> 

سنقوم الآن بمعالجة عنصر <p> المقابل الموجود في أسفل الصفحة ، على النحو التالي:

 <p>Your gender: {this.state.gender}</p> 

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


تطبيق في المتصفح

الآن دعونا نعمل على مربع التحرير والسرد. الشغل له يشبه هذا:

 <select>   <option></option>   <option></option>   <option></option>   <option></option> </select> 

يوضح هذا الرمز أننا نخطط لوصف مربع تحرير وسرد يحتوي على أربعة عناصر.

تحتوي العلامة <select> وعلاماتها <option> على سمة value . ومع ذلك ، فإن هذه الصفات تحمل معاني مختلفة. تشير قيمة value المعينة لعنصر <option> إلى ما يجب أن تكون عليه خاصية الحالة المقابلة عند تحديد هذا العنصر. هذه هي الخطوط التي يجب أن تكون في القائمة المنسدلة. في حالتنا ، هذه هي بعض الوجهات ، على سبيل المثال ، البلدان. دعنا نكتب أسمائهم بحرف صغير حتى يتوافق مظهرهم مع قيم خصائص value العناصر الأخرى في الكود. بعد ذلك ، سيبدو رمز مربع التحرير والسرد كما يلي:

 <select value=>   <option value="germany">Germany</option>   <option value="norway">Norway</option>   <option value="north pole">North Pole</option>   <option value="south pole">South Pole</option> </select> 

إذا تحدثنا عن سمة value <select> ، فلن تتم الإشارة هنا إلى بعض القيمة المرمّزة ، ولكن رابطًا إلى خاصية الحالة المقابلة:

 <select value={this.state.destination}>   <option value="germany">Germany</option>   <option value="norway">Norway</option>   <option value="north pole">North Pole</option>   <option value="south pole">South Pole</option> </select> 

تعيين الحقل سمات أخرى. على وجه الخصوص ، الاسم المطابق لاسم الخاصية في الولاية ، onChange أحداث onChange ، this.handleChange .

 <select   value={this.state.destination}   name="destination"   onChange={this.handleChange} >   <option value="germany">Germany</option>   <option value="norway">Norway</option>   <option value="north pole">North Pole</option>   <option value="south pole">South Pole</option> </select> 

سنقوم الآن بتهيئة وصف العنصر <p> ، والذي سيعرض ما تم تحديده في حقل destination :

 <p>Your destination: {this.state.destination}</p> 

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


تطبيق في المتصفح

لكي تندرج قيمة germany في الحالة ، تحتاج إلى فتح مربع التحرير والسرد وتحديد شيء آخر أولاً ، ثم تحديد Germany .

في كثير من الأحيان ، من أجل مراعاة هذه الميزة في حقول القائمة ، في قوائمها ، باعتبارها العنصر الأول ، فإنها تضع شيئًا ما كعنصر ذي قيمة فارغة وبنص مثل -- Please Choose a destination -- . في حالتنا ، قد يبدو مثل هذا:

 <select   value={this.state.destination}   name="destination"   onChange={this.handleChange} >   <option value="">-- Please Choose a destination --</option>   <option value="germany">Germany</option>   <option value="norway">Norway</option>   <option value="north pole">North Pole</option>   <option value="south pole">South Pole</option> </select> 

سوف نركز على هذا الخيار لتحديد مربع التحرير والسرد.

الآن دعنا نتعامل مع ، ربما ، الجزء الأكثر صعوبة من مهمتنا ، المرتبطة بالأعلام. هنا تجدر الإشارة إلى أن خاصية ممتلكات الدولة dietaryRestrictions ، والتي تم التخطيط لاستخدامها للعمل مع الأعلام ، تمت تهيئتها باستخدام صفيف فارغ. الآن ، عندما يتعلق الأمر بالعمل مع عناصر التحكم ، هناك شعور بأنه سيكون من الأفضل تمثيل هذا الحقل ككائن. لذلك سيكون أكثر ملاءمة للعمل مع الكيانات التي تمثل العلامات الفردية في شكل خصائص هذا الكائن مع أسماء مألوفة ، وليس في شكل عناصر مجموعة. ستحتوي خصائص الكائن ، والتي سيتم تمثيلها الآن بواسطة dietaryRestrictions حالة dietaryRestrictions النظام dietaryRestrictions ، على قيم منطقية تشير إلى ما إذا تم إلغاء تحديد خانة الاختيار المقابلة ( false ) أو تحديدها ( true ). الآن سيبدو رمز تهيئة الحالة كما يلي:

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   dietaryRestrictions: {       isVegan: false,       isKosher: false,       isLactoseFree: false   } } 

كما ترون ، نخطط لإنشاء ثلاثة أعلام. سيتم إعادة تعيين كل منهم ، فور تحميل الصفحة.

وصفنا العلامات الموجودة في الكود الذي تم إرجاعه بواسطة المكون ، ولفها بالعلامات <label> وتحديد سماتها. إليك ما سيبدو عليه الكود:

 <label>   <input       type="checkbox"       name="isVegan"       onChange={this.handleChange}       checked={this.state.dietaryRestrictions.isVegan}   /> Vegan? </label> <br /> <label>   <input       type="checkbox"       name="isKosher"       onChange={this.handleChange}       checked={this.state.dietaryRestrictions.isKosher}   /> Kosher? </label> <br /> <label>   <input       type="checkbox"       name="isLactoseFree"       onChange={this.handleChange}       checked={this.state.dietaryRestrictions.isLactoseFree}   /> Lactose Free? </label> 

أسماء العلامات المستخدمة هي أسماء الخصائص الخاصة dietaryRestrictions " dietaryRestrictions ، وقيم السمات التي تم checked منها هي إنشاءات للنموذج this.state.dietaryRestrictions.isSomething .

يرجى ملاحظة أنه على الرغم من onChange الموجود بالفعل على onChange أحداث this.handleChange ، يجب علينا إجراء بعض التغييرات على البرنامج لضمان عمل البرنامج بشكل صحيح.

نلقي نظرة على التطبيق.


تطبيق في المتصفح

كما ترون ، يتم عرض العلامات على الصفحة ، لكن المكون لا يحتوي حتى الآن على كل الآليات اللازمة لضمان التشغيل السليم. دعونا نتعامل مع معالج الأحداث.

هنا ، للعمل مع مربعات الاختيار ، نحتاج إلى استخراج event.target من الكائن ، بالإضافة إلى الخصائص المستخرجة بالفعل ، type والخصائص checked . الأول مطلوب للتحقق من نوع العنصر (الإشارات من النوع الذي يمثله سطر checkbox ) ، والثاني هو معرفة ما إذا كان مربع الاختيار محددًا أم غير محدد. إذا اتضح أنه تم استدعاء المعالج بعد تفاعل المستخدم مع العلم ، فإننا نستخدم إجراء إعداد خاص للحالة. سنتعامل مع أحداث عناصر التحكم الأخرى بالطريقة نفسها كما كان من قبل.

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

 handleChange(event) {   const {name, value, type, checked} = event.target   type === "checkbox" ?       this.setState({           dietaryRestrictions: {               [name]: checked           }       })   :   this.setState({       [name]: value   }) } 

إذا قمت بفتح صفحة التطبيق في متصفح ، وبعد تنزيلها مباشرة ، سيبدو كل شيء جيدًا ، عندما تحاول ، على سبيل المثال ، إدخال اسم في حقل First Name ، سيعمل كل شيء كما كان من قبل ، ولكن عندما تحاول تعيين أحد خانات الاختيار ، سيتم إصدار التحذير التالي :
تحذير: يقوم أحد المكونات بتغيير إدخال خاضع للتحكم في نوع الكتابة بحيث لا يمكن التحكم فيه. لا ينبغي تبديل عناصر الإدخال من التحكم إلى غير المنضبط (أو العكس). حدد بين استخدام عنصر تحكم متحكم فيه أو غير متحكم به طوال عمر المكون. مزيد من المعلومات: fb.me/react-controlled-components

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

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   isVegan: false,   isKosher: false,   isLactoseFree: false } 

سنقوم الآن بتغيير الإعدادات الخاصة بسمات الأعلام ، والتخلص من dietaryRestrictions :

 <label>   <input       type="checkbox"       name="isVegan"       onChange={this.handleChange}       checked={this.state.isVegan}   /> Vegan? </label> <br /> <label>   <input       type="checkbox"       name="isKosher"       onChange={this.handleChange}       checked={this.state.isKosher}   /> Kosher? </label> <br /> <label>   <input       type="checkbox"       name="isLactoseFree"       onChange={this.handleChange}       checked={this.state.isLactoseFree}   /> Lactose Free? </label> 

وأخيرًا ، قم بتحرير رمز العنصر الذي يعرض معلومات حول القيود الغذائية المحددة من قبل المستخدم:

 <p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p> 

بعد ذلك ، سوف نتحقق من صحة التطبيق.


تطبيق في المتصفح

كما ترون ، كل شيء يعمل كما هو متوقع.

إليك الرمز الكامل لمكون App :

 import React, {Component} from "react" class App extends Component {   constructor() {       super()       this.state = {           firstName: "",           lastName: "",           age: "",           gender: "",           destination: "",           isVegan: false,           isKosher: false,           isLactoseFree: false       }       this.handleChange = this.handleChange.bind(this)   }     handleChange(event) {       const {name, value, type, checked} = event.target       type === "checkbox" ?           this.setState({               [name]: checked           })       :       this.setState({           [name]: value       })   }     render() {       return (           <main>               <form>                   <input                       name="firstName"                       value={this.state.firstName}                       onChange={this.handleChange}                       placeholder="First Name"                   />                   <br />                                     <input                       name="lastName"                       value={this.state.lastName}                       onChange={this.handleChange}                       placeholder="Last Name"                   />                   <br />                                     <input                       name="age"                       value={this.state.age}                       onChange={this.handleChange}                       placeholder="Age"                   />                   <br />                                     <label>                       <input                           type="radio"                           name="gender"                           value="male"                           checked={this.state.gender === "male"}                           onChange={this.handleChange}                       /> Male                   </label>                                     <br />                                     <label>                       <input                           type="radio"                           name="gender"                           value="female"                           checked={this.state.gender === "female"}                           onChange={this.handleChange}                       /> Female                   </label>                                     <br />                                     <select                       value={this.state.destination}                       name="destination"                       onChange={this.handleChange}                   >                       <option value="">-- Please Choose a destination --</option>                       <option value="germany">Germany</option>                       <option value="norway">Norway</option>                       <option value="north pole">North Pole</option>                       <option value="south pole">South Pole</option>                   </select>                                     <br />                                     <label>                       <input                           type="checkbox"                           name="isVegan"                           onChange={this.handleChange}                           checked={this.state.isVegan}                       /> Vegan?                   </label>                   <br />                                     <label>                       <input                           type="checkbox"                           name="isKosher"                           onChange={this.handleChange}                           checked={this.state.isKosher}                       /> Kosher?                   </label>                   <br />                                     <label>                       <input                           type="checkbox"                           name="isLactoseFree"                           onChange={this.handleChange}                           checked={this.state.isLactoseFree}                       /> Lactose Free?                   </label>                   <br />                                     <button>Submit</button>               </form>               <hr />               <h2><font color="#3AC1EF">Entered information:</font></h2>               <p>Your name: {this.state.firstName} {this.state.lastName}</p>               <p>Your age: {this.state.age}</p>               <p>Your gender: {this.state.gender}</p>               <p>Your destination: {this.state.destination}</p>               <p>Your dietary restrictions:</p>                             <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p>               <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p>               <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p>                         </main>       )   } } export default App 

النتائج


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

أعزائي القراء! أخبرني ، هل كان من الصعب إكمال هذا العمل العملي؟

Source: https://habr.com/ru/post/ar446208/


All Articles