React.js: دليل المبتدئين

يعتقد مؤلف المقال ، الذي ننشر ترجمته ، أن معظم أدلة رد الفعل الحالية ، للأسف ، لا تولي الاهتمام الواجب لتقنيات التطوير العملية القيمة. لا تقدم هذه الأدلة دائمًا للشخص المعني فيها فهمًا لما هو "النهج الصحيح" للعمل مع التفاعل.

الصورة

سيغطي هذا البرنامج التعليمي ، الذي يهدف إلى بدء المطورين بمعرفة HTML و JavaScript و CSS ، أساسيات React والأخطاء الأكثر شيوعًا التي قد يواجهها المبرمج الذي يستخدم هذه المكتبة.

لماذا يختار مطورو الويب رد فعل؟


قبل أن نبدأ العمل ، دعنا نقول بضع كلمات حول لماذا يمكن اعتبار React البديل الأفضل بين أدوات تطوير واجهات الويب. هناك العديد من أطر عمل واجهة المستخدم. لماذا تختار رد فعل؟ للإجابة على هذا السؤال ، دعنا نقارن بين أكثر أدوات تطوير الواجهة شيوعًا - React و Angular. تجدر الإشارة إلى أن إطار Vue.js ، الذي يكتسب شعبية ، يمكن تضمينه في هذه المقارنة ، لكننا سنقتصر على React و Angular.

approach نهج تعريفي لوصف الواجهات


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

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

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

▍ بناء جملة واضح


يستخدم الرمز الزاوي توجيهات مثل ng-model و ngIf و ngFor . يبدو هذا الرمز مرهقًا إلى حد ما. في React ، من ناحية أخرى ، يتم استخدام بناء جملة JSX ، والذي يُنظر إليه على أنه HTML عادي ، أي من أجل بدء تطوير التفاعل ، لا تحتاج إلى تعلم أشياء جديدة بشكل أساسي. إليك ما يبدو عليه:

 const Greetings = ({ firstName }) => (  <div>Hi, {firstName}</div> ); 

cur منحنى التعلم الصحيح


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

إذا قمت بتحليل Angular ، اتضح أنه إذا قررت إتقان هذا الإطار ، فسيتعين عليك تعلم لغة جديدة (تستخدم Angular TypeScript) ، بالإضافة إلى تعلم كيفية استخدام أدوات سطر الأوامر Angular والتعود على العمل مع التوجيهات.

▍ ميزات آلية ربط البيانات


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

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

approach النهج الوظيفي للتنمية


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

في React ، يمكن التعبير عن جميع مكونات واجهة المستخدم كمجموعات من الوظائف النقية. يمكن مقارنة استخدام الوظائف النقية لتكوين واجهة مستخدم بتنفس الهواء النقي.

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

رد فعل تطوير التطبيقات


▍ العقدة. js


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

▍إعداد المشروع


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

لتثبيت تطبيق create-react-app ، استخدم هذا الأمر:

 npm i -g create-react-app 

بعد ذلك ، لإنشاء قالب التطبيق ، قم بتشغيل الأمر التالي:

 create-react-app react-intro 

تم الانتهاء من هذا التحضير الأولي. لتشغيل التطبيق ، قم بتشغيل الأوامر التالية:

 cd react-intro npm start 

ننتقل هنا إلى مجلد المشروع ونطلق خادم التطوير ، والذي يسمح لك بفتح تطبيق React جديد بالانتقال إلى المتصفح على http: // localhost: 3000 / .

structure هيكل المشروع


دعنا نكتشف كيف يعمل تطبيق React. للقيام بذلك ، افتح المشروع الذي أنشأته للتو باستخدام IDE (أوصي بـ Visual Studio Code ).

ملف Index.html


في مجلد المشروع ، افتح الملف الموجود على public/index.html . إليك ما ستراه من خلال القيام بذلك.


ملف Index.html

نحن هنا مهتمون بشكل خاص بالسطر <div id="root"> . هذا هو المكان الذي سيقع فيه تطبيق React الخاص بنا. سيتم استبدال كل هذا العنصر برمز التطبيق ، وسيبقى كل شيء آخر دون تغيير.

ملف Index.js


افتح الآن src/index.js . هذا الملف هو الذي ينشر تطبيق React. وبالمناسبة ، سيتم وضع شفرة المصدر للتطبيق في دليل src .


ملف Index.js

إليك سطر الكود المسؤول عن إخراج ما نسميه "تطبيق رد الفعل" على الصفحة:

 ReactDOM.render(<App />, document.getElementById('root')); 

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

الآن سنتعامل مع بناء <App /> . وهي تشبه إلى حد كبير كود HTML ، لكنها عينة من كود JSX ، وهي صيغة JavaScript خاصة تستخدمها React. يرجى ملاحظة أن هذا البناء يبدأ بحرف كبير A ، وهو بالضبط <App /> ، وليس <app /> . هذا بسبب اصطلاح تسمية الكيان المستخدم في React. يسمح هذا النهج للنظام بالتمييز بين علامات HTML العادية ومكونات التفاعل. إذا لم تكن أسماء المكونات مكتوبة بحروف كبيرة ، فلن تتمكن React من عرضها على الصفحة.

إذا كنت تخطط لاستخدام JSX في ملف. .js معين ، فستحتاج إلى استيراد React هناك باستخدام الأمر التالي:

 import React from 'react'; 

ملف App.js


نحن الآن على استعداد لإلقاء نظرة على رمز المكون الأول. للقيام بذلك ، افتح src/App.js


ملف App.js

لإنشاء مكون React ، يجب عليك أولاً إنشاء فئة سلالة React.Component . هذا هو بالضبط ما class App extends Component يحل خط class App extends Component . يجب أن تحتوي جميع مكونات React على تنفيذ لطريقة render ، حيث ، كما يمكنك التخمين من اسمه ، يتم تقديم المكون ويتم إنشاء وصف لتمثيله المرئي. يجب أن ترجع هذه الطريقة ترميز HTML للإخراج إلى الصفحة.

لاحظ أن سمة className مكافئة لسمة class في HTML. يتم استخدامه لتعيين فئات CSS للعناصر من أجل نمطها. class الكلمة الأساسية JavaScript محجوزة ولا يمكن استخدامها كاسم سمة.

دعنا نكرر ما اكتشفناه للتو عن المكونات:

  1. تبدأ أسمائهم بحرف كبير ( A في App ).
  2. إنها تمد فئة React.Component .
  3. يجب عليهم تنفيذ طريقة render ترجع الترميز.

الآن دعونا نتحدث عن ما يجب تجنبه أثناء تطوير تطبيقات React.

ec التوصية رقم 1: ليس من الضروري استخدام فئات المكونات في كل مكان


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

ما هو الخطأ في وصف المكونات باستخدام آلية الفصل؟ والحقيقة هي أنه من الصعب اختبار هذه المكونات وتميل إلى النمو بشكل مفرط. تخضع هذه المكونات لمشكلة الفصل الرديء للمسؤوليات ، وخلط المنطق والعرض المرئي (وهذا يعقّد تصحيح التطبيقات واختبارها). بشكل عام ، يؤدي استخدام فئات المكونات إلى حقيقة أن المبرمج ، المجازي ، "يطلق النار على نفسه في القدم". لذلك ، خاصة عندما يتعلق الأمر بالمبرمجين المبتدئين ، فإنني أوصي بعدم استخدام فئات المكونات على الإطلاق.

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

 function App() { return (   <div className="App">     ...   </div> ); } export default App; 

انظر ماذا فعلنا هنا؟ وبالتحديد ، أزلنا الفصل واستبدلنا طريقة render ببناء function App() {...} النموذج function App() {...} . إذا استخدمنا بنية دالة السهم ES6 هنا ، فستبدو الشفرة لدينا أفضل:

 const App = () => ( <div className="App">   ... </div> ); export default App; 

قمنا بتحويل الفصل إلى دالة تقوم بإرجاع الترميز المطلوب عرضه على الصفحة.

فكر في هذا. لا تحتوي الدالة التي ترجع الترميز على رمز مرجعي. هذا هو تقريبًا ترميز نقي. أليس هذا مثاليًا؟

رمز المكونات الوظيفية أسهل بكثير في القراءة ، والعمل معها ، يجب أن تكون أقل تشتيتًا بالتصاميم القياسية.

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

▍ التعرف على الخصائص


الخصائص (الدعائم) هي أحد المفاهيم المركزية للتفاعل. ما هي "الخصائص"؟ لفهم ذلك ، تذكر المعلمات التي تم تمريرها إلى الوظائف. في الأساس ، الخصائص هي المعلمات التي يتم تمريرها إلى المكونات. خذ بعين الاعتبار الرمز التالي:

 const Greetings = (props) => <div>Hey you! {props.firstName} {props.lastName}!</div>; const App = () => ( <div>   <Greetings firstName="John" lastName="Smith" /> </div> ); 

هنا أنشأنا مكون Greetings واستخدمناه لتحية رجل اسمه John Smith من مكون App . سيؤدي كل هذا الرمز إلى ترميز HTML التالي:

 <div>  <div>Hey you! John Smith!</div> </div> 

يتم استخدام الأقواس {props.name} في تعبيرات مثل {props.name} لتمييز شفرة JavaScript. يتم تمرير مكون Greetings ، في شكل معلمات ، خصائص lastName و lastName . نحن نعمل معهم ، في إشارة إلى خصائص كائن props .

لاحظ أنه يتم props كائن props المفردة props ، وليس قيمتين lastName خصائص lastName و lastName .

يمكن تبسيط الكود من خلال الاستفادة من قدرة ES6 على إعادة هيكلة الكائنات:

 const Greetings = ({ firstName, lastName }) => <div>Hey you! {firstName} {lastName}!</div>; 

كما ترى ، هنا تم استبدال البناء (props) بـ ({ firstName, lastName }) . مع هذا الاستبدال ، نقول للنظام أننا مهتمون فقط props لكائن props . وهذا بدوره يسمح لنا بالوصول مباشرة إلى قيم firstName و lastName دون تحديد خصائص الكائن بشكل صريح مثل props.firstName .

ماذا لو حلنا نفس المشكلة بدلاً من المكونات الوظيفية ، سنستخدم المكونات القائمة على الفصل؟ في هذه الحالة ، سيبدو رمز مكون Greetings كما يلي:

 class Greetings extends React.Component { render() {   return (     <div>Hey you! {this.props.firstName} {this.props.lastName}!</div>   ); } } 

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

responsibility مبدأ المسؤولية الوحيدة


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

كيف يمكن انتهاك مبدأ المسؤولية الوحيدة؟ يحدث هذا غالبًا عندما يتم وضع آليات غير مرتبطة ببعضها البعض في نفس الملفات. في هذه المادة سنشير غالبًا إلى هذا المبدأ.

عادة ما يضع المبتدئون العديد من المكونات في ملف واحد. على سبيل المثال ، لدينا الكود الخاص بمكونات Greetings App في نفس الملف. من الناحية العملية ، لا ينبغي القيام بذلك ، لأن هذا ينتهك برنامج التقويم الاستراتيجي.

حتى المكونات الصغيرة جدًا (مثل مكون Greetings بنا) يجب وضعها في ملفات منفصلة.

ضع رمز مكون Greetings في ملف منفصل:

 import React from "react"; const Greetings = ({ firstName, lastName }) => (   <div>       Hey you! {firstName} {lastName}!   </div> ); export default Greetings; 

ثم استخدم هذا المكون في مكون App :

 import Greetings from "./Greetings"; const App = () => ( ... ); 

لاحظ أن اسم الملف يجب أن يتطابق مع اسم المكون. أي ، يجب وضع رمز مكون App في ملف App.js ، ورمز مكون Greetings في ملف Greetings ، وما إلى ذلك.

▍ الإلمام بحالة التطبيق


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

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

 import React from "react"; class SimpleForm extends React.Component { render() {   return (     <div>       <input type="text" name="firstName" />       <Greetings firstName="John" />     </div>   ); } } const App = () => ( <div>   <SimpleForm /> </div> ); 

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

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

 class SimpleForm extends React.Component { state = {   firstName: "", }; onFirstNameChange = event =>   this.setState({     firstName: event.target.value   }); render() {   return (     <div>       <input type="text" name="firstName" onChange={this.onFirstNameChange} />       <Greetings firstName={this.state.firstName} />     </div>   ); } } 

يمكنك تخيل حالة ككائن JavaScript بسيط ، يتم تخزينه ، في شكل خاصية ، في فئة مكون SimpleForm . في هذا الكائن ، نضيف خاصية firstName .

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

 this.setState(...) 

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

 { firstName: event.target.value } 

في هذه الحالة ، event.target.value هو ما أدخله المستخدم في حقل النموذج ، أي اسمه.

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

heckتحقق من البيانات المدخلة في النموذج


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

قم بإضافة معالج الأحداث onBlur إلى المكون ، والذي يتم استدعاؤه عندما يترك المستخدم حقل الإدخال. قم بإضافة خاصية أخرى إلى حالة التطبيق - firstNameError . إذا حدث خطأ أثناء إدخال الاسم ، فسنعرض رسالة حول هذا تحت الحقل.

دعونا نحلل هذا الرمز.

 class SimpleForm extends React.Component { state = {   firstName: "",   firstNameError: "", }; validateName = name => {   const regex = /[A-Za-z]{3,}/;   return !regex.test(name)     ? "The name must contain at least three letters. Numbers and special characters are not allowed."     : ""; }; onFirstNameBlur = () => {   const { firstName } = this.state;   const firstNameError = this.validateName( firstName );   return this.setState({ firstNameError }); }; onFirstNameChange = event =>   this.setState({     firstName: event.target.value   }); render() {   const { firstNameError, firstName } = this.state;   return (     <div>       <div>         <label>           First name:           <input             type="text"             name="firstName"             onChange={this.onFirstNameChange}             onBlur={this.onFirstNameBlur}           />           {firstNameError && <div>{firstNameError}</div>}         </label>       </div>       <Greetings         firstName={firstName}       />     </div>   ); } } 

حالة الطلب


بتطوير نظام للتحقق من المدخلات ، قمنا في البداية بإضافة خاصية جديدة إلى الحالة: firstNameError :

 state = {  ...  firstNameError: "", }; 

وظيفة التحقق من صحة البيانات


يتم التحقق من صحة البيانات في وظيفة السهم ValidateName. يتحقق من صحة الاسم الذي تم إدخاله بتعبير عادي:

 validateName = name => { const regex = /[A-Za-z]{3,}/; return !regex.test(name)    ? "The name must contain at least three letters..."    : ""; } 

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

معالج الأحداث OnBlur


onBlur نظرة على onBlur الأحداث onBlur ، والذي يتم استدعاؤه عندما يترك المستخدم حقل الإدخال:

 onFirstNameBlur = () => { const { firstName } = this.state; const firstNameError = this.validateName( firstName ); return this.setState({ firstNameError }); }; 

هنا firstName خاصية firstName من الحالة ، مستفيدين من قدرة ES6 على تدمير الكائنات. السطر الأول من هذا الرمز يعادل هذا:

 const firstName = this.state.firstName; 

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

طريقة التقديم


خذ بعين الاعتبار طريقة render() المكون render() :

 render() {  const { firstNameError, firstName} = this.state;  ... } 

.

 <input ... onBlur={this.onFirstNameBlur} /> 

onFirstNameBlur onBlur .

 {firstNameError && <div>{firstNameError}</div>} 

JavaScript. div , , , firstNameError true .


, , , . , :

 render() { const { firstNameError, firstName } = this.state; return (   <div       style={{         margin: 50,         padding: 10,         width: 300,         border: "1px solid black",         backgroundColor: "black",         color: "white"       }}     >     <div style={{marginBottom: 10}}>       <label>         First name:         <input           style={{backgroundColor: '#EFEFFF', marginLeft: 10}}           type="text"           name="firstName"           onChange={this.onFirstNameChange}           onBlur={this.onFirstNameBlur}         />         {firstNameError && <div style={{color: 'red', margin: 5}}>{firstNameError}</div>}       </label>     </div>     <Greetings       firstName={firstName}     />   </div> ); } 

React style .

, , , , , . , .




▍ №2:


, , React-. , , — render , , . ? , . , , .

? , . style , . . , style.js :

 // style.js: const style = {   form: {       margin: 50,       padding: 10,       width: 300,       border: "1px solid black",       backgroundColor: "black",       color: "white"   },   inputGroup: {       marginBottom: 10   },   input: {       backgroundColor: "#EFEFFF",       marginLeft: 10   },   error: {       color: "red",       margin: 5   } }; export default style; 

, , SimpleComponent :

 import style from './style'; class SimpleForm extends React.Component {   ...       render() {       const { firstNameError, firstName } = this.state;         return (         <div style={style.form}>           <div style={style.inputGroup}>             <label>               First name:               <input                 style={style.input}                 type="text"                 name="firstName"                 onChange={this.onFirstNameChange}                 onBlur={this.onFirstNameBlur}               />               {firstNameError && (                 <div style={style.error}>{firstNameError}</div>               )}             </label>           </div>             <Greetings firstName={firstName} />         </div>       );     } } export default SimpleForm; 

, . .


, :

 class SimpleForm extends React.Component { state = {   ...   lastName: "",   lastNameError: "" }; validateName = ...; onFirstNameBlur = ...; onFirstNameChange = ...; onLastNameBlur = () => {   const { lastName } = this.state;   const lastNameError = this.validateName(lastName);   return this.setState({ lastNameError }); }; onLastNameChange = event =>   this.setState({     lastName: event.target.value   }); render() {   const { firstNameError, firstName, lastName, lastNameError } = this.state;   return (     <div style={style.form}>       <div style={style.inputGroup}>         <label>           First name:           <input             style={style.input}             type="text"             name="firstName"             onChange={this.onFirstNameChange}             onBlur={this.onFirstNameBlur}           />           {firstNameError && <div style={style.error}>{firstNameError}</div>}         </label>       </div>       <div style={style.inputGroup}>         <label>           Last name:           <input             style={style.input}             type="text"             name="lastName"             onChange={this.onLastNameChange}             onBlur={this.onLastNameBlur}           />           {lastNameError && <div style={style.error}>{lastNameError}</div>}         </label>       </div>       <Greetings firstName={firstName} lastName={lastName} />     </div>   ); } } export default SimpleForm; 

— , firstName .

«»? — , .

▍ №3:


, , , , , . , , render . .

, , , . TextField , .

 import React from 'react' import style from "./style"; const TextField = ({name, onChange, onBlur, error, label}) => ( <div style={style.inputGroup}>   <label>     {label}     <input       style={style.input}       type="text"       name={name}       onChange={onChange}       onBlur={onBlur}     />     {error && <div style={style.error}>{error}</div>}   </label> </div> ); export default TextField; 

, , render . , , .

SimpleForm :

 ... import TextField from './TextField'; class SimpleForm extends React.Component { ... render() {   const { firstNameError, firstName, lastName, lastNameError } = this.state;   return (     <div style={style.form}>       <TextField name="firstName"                  label="First name:"                  onChange={this.onFirstNameChange}                  onBlur={this.onFirstNameBlur}                  error={firstNameError} />       <TextField name="lastName"                  label="Last name:"                  onChange={this.onLastNameChange}                  onBlur={this.onLastNameBlur}                  error={lastNameError} />       <Greetings firstName={firstName} lastName={lastName} />     </div>   ); } } 

, . , TextField . FirstNameField :

 import React from 'react'; import TextField from './TextField'; const FirstNameField = ({...rest}) => ( <TextField name="firstName"             label="First name:"             {...rest} /> ); export default FirstNameField; 

, . ({...rest}) ( rest, ). , , , rest . , , TextField , « », spread (, {...rest} , ). rest , , TextField .

, : , FirstNameField TextField .

LastNameField :
:

 ... import FirstNameField from './FirstNameField'; import LastNameField from './LastNameField'; class SimpleForm extends React.Component { ... render() {   const { firstNameError, firstName, lastName, lastNameError } = this.state;   return (     <div style={style.form}>       <FirstNameField onChange={this.onFirstNameChange}                       onBlur={this.onFirstNameBlur}                       error={firstNameError} />       <LastNameField onChange={this.onLastNameChange}                       onBlur={this.onLastNameBlur}                       error={lastNameError} />       <Greetings firstName={firstName} lastName={lastName} />     </div>   ); } } 

.


, , , :

  • , , , .
  • . , , , , 1000 ( ).
  • , . , , .
  • , , , . . , , . , , , .
  • , , , , .
  • this , .

الملخص


, React- . , , , , . , , , React, , , , UI-.

→ , ,

أعزائي القراء! , , React-, .

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


All Articles