كتاب الرد السريع. تطبيقات الويب في React و JSX و Redux و GraphQL »

صورة مرحبا ، habrozhiteli! تم إصدار الإصدار الأصلي في خريف عام 2017 ، لكنه لا يزال يعتبر أفضل كتاب لاستكشاف React. يقوم المؤلف باستمرار بتحديث وتعديل رمز الكتاب في مستودع جيثب .

نقترح في منشور ما التعرف على المقطع "الدول ودورها في الطبيعة التفاعلية لرد الفعل"

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


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

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

أحد الحلول الممكنة هو تقديم عنصر بخصائص جديدة في كل مرة تتلقى فيها استجابة جديدة من الخادم. ولكن بعد ذلك يجب عليك وضع المنطق خارج المكون - ويتوقف المكون عن تحقيق الاكتفاء الذاتي. من الواضح أنه إذا تعذر تغيير قيم الخاصية ، ويجب أن يكون الإكمال التلقائي مكتفًا ذاتيًا ، فمن المستحيل استخدام الخصائص. ثم يطرح السؤال: كيفية تحديث طرق العرض استجابة للأحداث دون إعادة إنشاء المكون (createElement () أو JSX <NAME />)؟ هذه هي المشكلة التي تحلها الدول.

صورة

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

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

ما هي حالة مكون التفاعل؟


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

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

عند العمل مع الدول ، يمكنك الوصول إليهم بالاسم. الاسم هو سمة (أي ، مفتاح كائن أو خاصية كائن - ليست خاصية مكوّن) لكائن this.state ، على سبيل المثال this.state.autocompleMatches أو this.state.inputFieldValue.

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

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

يستخدم مطورو React حالات لإنشاء واجهات مستخدم جديدة. خصائص المكون (this.props) والمتغيرات العادية (inputValue) وسمات الفئة (this.inputValue) ليست مناسبة لهذا ، لأن تغيير قيمها (في سياق المكون الحالي) لا يؤدي إلى تغيير في طريقة العرض. على سبيل المثال ، المقتطف التالي هو antipattern ، مما يدل على أن تغيير القيمة في أي مكان باستثناء الحالة لن يؤدي إلى تحديث المشاهدة:

// :   ! let inputValue = 'Texas' class Autocomplete extends React.Component { updateValues() ← {      ( ) this.props.inputValue = 'California' inputValue = 'California' this.inputValue = 'California' } render() { return ( <div> {this.props.inputValue} {inputValue} {this.inputValue} </div> ) } } 

الآن دعونا نرى كيفية العمل مع حالات مكونات React.

العمل مع الدول


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

الوصول إلى الدول


كائن الحالة هو سمة للمكون ، ويجب عليك الوصول إليه من خلال هذا الرابط ، على سبيل المثال this.state.name. كما تتذكر ، يمكن الوصول إلى المتغيرات وعرضها في كود JSX في الأقواس المتعرجة ({}). وبالمثل ، في render () ، يمكنك تقديم this.state (مثل أي متغير آخر أو سمة فئة مكون غير قياسي) ، على سبيل المثال {this.state.inputFieldValue}. يشبه بناء الجملة بناء الجملة للوصول إلى الخصائص في this.props.name.

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

يحتوي المشروع على الهيكل التالي:

 /clock index.html /jsx script.jsx clock.jsx /js script.js clock.js react.js react-dom.js 

يمكنني استخدام Babel CLI مع تتبع الإشارات (-w) والدليل (-d) لتجميع جميع ملفات مصدر JSX من الساعة / jsx إلى مجلد clock / js المستهدف وإعادة ترجمة عند اكتشاف التغييرات. بالإضافة إلى ذلك ، قمت بحفظ الأمر كبرنامج نصي npm في ملف package.json الخاص بالمجلد الأصلي ch04 لتنفيذ الأمر build-clock npm من ch04:

 "scripts": { "build-clock": "./node_modules/.bin/babel clock/jsx -d clock/js -w" }, 

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

القائمة 4.1. تقديم حالة JSX

 class Clock extends React.Component { render() { return <div>{this.state.currentTime}</div> } } ReactDOM.render( <Clock />, document.getElementById('content') ) 

ستتلقى رسالة خطأ: TypeError Uncaught: لا يمكن قراءة خاصية 'currentTime' خالية. عادةً ما يكون لرسائل خطأ جافا سكريبت JavaScript نفس فوائد كوب من الماء البارد لشخص غارق. من الجيد أنه في هذه الحالة على الأقل ، يعرض JavaScript رسالة ذات معنى.

تشير الرسالة إلى أن قيمة currentTime غير محددة. على عكس الخصائص ، لا يتم تعيين الحالات في الأصل. فشل استدعاء setState في render () أيضًا ، لأنه سيؤدي إلى إنشاء حلقة (setState -> render -> setState ...) - وسيبلغ React عن خطأ.

احالة الحالة الأولية


لقد رأيت ذلك بالفعل قبل استخدام بيانات الحالة في التقديم () ، يجب تهيئة الحالة. لتعيين الحالة الأولية ، استخدم this.state في المنشئ مع بناء جملة فئة ES6 React.Component. تذكر استدعاء super () مع الخصائص ؛ خلاف ذلك ، لن يعمل المنطق في الأصل (React.Component):

 class MyFancyComponent extends React.Component { constructor(props) { super(props) this.state = {...} } render() { ... } } 

عند تعيين الحالة الأولية ، يمكنك أيضًا إضافة منطق آخر - على سبيل المثال ، قم بتعيين قيمة currentTime باستخدام Date () جديد. يمكنك حتى استخدام toLocaleString () للحصول على تنسيق التاريخ / الوقت الصحيح للموقع الحالي للمستخدم ، كما هو موضح أدناه (ch04 / clock).

القائمة 4.2. منشئ مكون على مدار الساعة

 class Clock extends React.Component { constructor(props) { super(props) this.state = {currentTime: (new Date()).toLocaleString()} } ... } 

يجب أن تكون قيمة this.state كائنًا. لن ندخل في تفاصيل المنشئ () من ES6 ؛ ارجع إلى الملحق "د" وملخص ES6 على github.com/azat-co/cheatsheets/tree/master/es6. خلاصة القول هي أنه ، كما هو الحال في لغات OOP الأخرى ، يتم استدعاء المُنشئ (أي constructor ()) عند إنشاء مثيل للفئة. يجب أن يكون اسم طريقة المنشئ هو ذلك ؛ النظر في هذا واحد من قواعد ES6. بالإضافة إلى ذلك ، عند إنشاء طريقة constructor () ، يجب دائمًا تضمين المكالمة super () دائمًا ، وبدونها لن يتم تنفيذ مُنشئ الأصل. من ناحية أخرى ، إذا لم تقم بتحديد طريقة constructor () ، فسيتم افتراض الدعوة إلى super () افتراضيًا.

اسم currentTime اختياري ؛ يجب عليك استخدام نفس الاسم لاحقًا عند قراءة هذه الحالة وتحديثها.

قد يحتوي كائن الحالة على كائنات متداخلة أو صفائف. يضيف المثال التالي مجموعة من أوصاف الكتب إلى الحالة:

 class Content extends React.Component { constructor(props) { super(props) this.state = { githubName: 'azat-co', books: [ 'pro express.js', 'practical node.js', 'rapid prototyping with js' ] } } render() { ... } } 

يتم استدعاء الأسلوب constructor () مرة واحدة فقط ، عند إنشاء عنصر React استنادًا إلى الفصل الدراسي. وبالتالي ، يمكنك تعيين الحالة مباشرةً باستخدام this.state مرة واحدة فقط - في طريقة المُنشئ (). لا تقم بتعيين أو تحديث الحالة مباشرة مع this.state = ... في مكان آخر ، حيث قد يؤدي ذلك إلى عواقب غير متوقعة.

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

تحديث الحالة


يتم تغيير الحالة بواسطة طريقة فئة this.setState (البيانات ، رد الاتصال). عند استدعاء هذه الطريقة ، يجمع React بين البيانات والحالات الحالية ويدعو render () ، وبعد ذلك يستدعي رد الاتصال.

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

إذا افترضت ببساطة أن الحالة قد تم تحديثها دون انتظار إكمال setState () ، أي للعمل بشكل متزامن عند إجراء عملية غير متزامنة ، فقد يحدث خطأ: يعتمد البرنامج على تحديث قيم الحالة ، ولكن تظل الحالة قديمة.
حتى الآن ، قدمنا ​​الوقت من الدولة. أنت تعرف بالفعل كيفية تعيين الحالة الأولية ، ولكن يجب تحديثه كل ثانية ، أليس كذلك؟ للقيام بذلك ، استخدم setInterval () وظيفة جهاز ضبط وقت المستعرض (http://mng.bz/P2d6) ، والتي ستقوم بتحديث الحالة كل ميلي ثانية. يتم تطبيق طريقة setInterval () في جميع المتصفحات الحديثة تقريبًا على أنها عالمية ، مما يعني أنه يمكن استخدامها دون أي مكتبات أو بادئات إضافية. مثال:

 setInterval(()=>{ console.log('Updating time...') this.setState({ currentTime: (new Date()).toLocaleString() }) }, 1000) 

لبدء العد التنازلي ، تحتاج إلى استدعاء setInterval () مرة واحدة فقط. نقوم بإنشاء طريقة launchClock () فقط لهذا الغرض ؛ ستطلق launchClock () في المنشئ. يتم عرض الإصدار النهائي للمكون في القائمة 4.3 (ch04 / clock / jsx / clock.jsx).

صورة

يمكن استدعاء طريقة setState () في أي مكان ، وليس فقط في طريقة launchClock () (والتي تسمى في المُنشئ) ، كما في المثال. عادةً ما يتم استدعاء أسلوب setState () من معالج الأحداث أو كاستدعاء عند تلقي البيانات أو تحديثها.

نصيحة: لن تؤدي محاولة تغيير الحالة في الكود باستخدام أمر من هذا .state.name = 'اسم جديد' إلى أي شيء. لن يؤدي ذلك إلى إعادة تقديم نموذج DOM الحقيقي وتحديثه ، وهو ما تريده. في معظم الحالات ، يكون تغيير الحالة المباشر بدون setState () مضادًا ويجب تجنبه.

من المهم ملاحظة أن أسلوب setState () لا يؤدي إلا إلى تحديث الحالات التي تم تمريرها إليها (جزئيًا أو مدمج ، ولكن دون استبدال كامل). لا يحل محل كائن الحالة بالكامل في كل مرة. لذلك ، إذا تغيرت واحدة فقط من الولايات الثلاث ، فستبقى الدولتان الأخريان دون تغيير. في المثال التالي ، لن يتغير userEmail و userId:

 constructor(props) { super(props) this.state = { userName: 'Azat Mardan', userEmail: 'hi@azat.co', userId: 3967 } } updateValues() { this.setState({userName: 'Azat'}) } 

إذا كنت تنوي تحديث الحالات الثلاث ، فسيتعين عليك القيام بذلك بشكل صريح عن طريق تمرير القيم الجديدة لهذه الحالات إلى setState (). (أيضًا في الكود القديم ، الذي لم يعد يعمل الآن ، يتم العثور على طريقة this.replaceState () أحيانًا ؛ يتم إهمالها رسميًا 1. كما قد تخمين بالاسم ، فقد استبدلت كائن الحالة بالكامل بكل سماته.)

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

كما ذكرنا سابقًا ، يمكن الوصول إلى كائن الحالة في إدخال this.state. في JSX ، يتم وضع قيم الإخراج في أقواس متعرجة ({}) ، وبالتالي ، لإعلان خاصية الحالة في طريقة عرض (أي ، في أمر الإرجاع لطريقة التجسيد) ، استخدم الترميز {this.state.NAME}.

يحدث React magic عندما تستخدم بيانات الحالة في طريقة عرض (على سبيل المثال ، في الإخراج ، في أمر if / else ، كقيمة سمة أو قيمة خاصية لطفل) ، ثم تقوم بتمرير قيم setState () جديدة. باه! React بتحديث كل علامات HTML اللازمة لك. يمكنك التحقق من ذلك في وحدة التحكم DevTools ، حيث يجب عرض الدورتين "تحديث ..." و "التقديم ...". والشيء الرائع هو أن هذا سيؤثر فقط على الحد الأدنى المطلق لعناصر DOM المطلوبة.

»يمكن الاطلاع على مزيد من المعلومات حول الكتاب على موقع الناشر
» المحتويات
» مقتطفات

20 ٪ من القسيمة للباعة المتجولين - رد الفعل

عند دفع النسخة الورقية من الكتاب ، يتم إرسال نسخة إلكترونية من الكتاب عن طريق البريد الإلكتروني.

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


All Articles