كيف تصبح محترفًا مع React setState () في 10 دقائق

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

فقط اقرأ واستمتع!

لذا تناول كوبًا من القهوة واستمر في القراءة! ؟

المفاهيم الأساسية لـ setState ()

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

من الناحية المفاهيمية ، تشبه المكونات وظائف JavaScript. يقبلون مدخلات عشوائية (تسمى "props") ويعيدون عناصر React التي تصف ما يجب أن يظهر على الشاشة.

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

سواء كنت تعلن عن أحد المكونات كدالة أو فئة ، يجب ألا يقوم بتعديل الدعائم الخاصة به مطلقًا.

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

بالطبع ، تكون واجهات مستخدم التطبيق ديناميكية وتتغير بمرور الوقت. لهذا السبب stateتم إنشاؤه.

State يسمح لمكونات React بتغيير مخرجاتها بمرور الوقت استجابةً لإجراءات المستخدم واستجابات الشبكة وأي شيء آخر ، دون انتهاك هذه القاعدة.

المكونات المعرفة على أنها فئات لها بعض الميزات الإضافية. الحالة المحلية هي ميزة متاحة فقط لفئة المكونات.

setState هي طريقة API المتوفرة مع المكتبة بحيث يكون المستخدم قادرًا على تحديد الحالة ومعالجتها بمرور الوقت.

ثلاث قواعد للإبهام عند استخدام setState ()

لا تعدل الحالة مباشرة

قد تكون تحديثات الحالة غير متزامنة

قد يُجمع React عدة setState()مكالمات في تحديث واحد للأداء.

لأن this.props و this.stateيمكن تحديثها بشكل غير متزامن، يجب أن لا تعتمد على قيمهم لحساب الدولة القادمة.

يتعين عليك أن تفعل دائما هذا النوع من التلاعب مع نهج وظيفي، وتزويد stateو propsوالعودة الجديدة stateعلى أساس السابق.

يتم دمج تحديثات الحالة

عندما تتصل setState()، تدمج React الكائن الذي توفره في الحالي state.

في المثال أدناه ، نقوم بتحديث المتغير dogNeedsVaccinationبشكل مستقل عن stateالمتغيرات الأخرى .

الدمج ضحل ، لذلك this.setState({ dogNeedsVaccination: true }) يترك المتغيرات الأخرى سليمة ، لتحل محل قيمة dogNeedsVaccination.

احترم تدفق البيانات وتجنب ذكر الحد الأقصى

تتدفق البيانات! لا يمكن لأي من المكونات الرئيسية أو الفرعية معرفة ما إذا كان أحد المكونات ذات حالة أو عديمة الحالة ، ولا ينبغي أن يهتموا بما إذا كان يتم تعريفه على أنه وظيفة أو فئة.

لهذا السبب stateغالبًا ما يطلق عليه محلي أو مغلف. لا يمكن الوصول إليه من قبل أي مكون آخر غير المكون الذي يمتلكه ويقوم بتعيينه.

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

دعنا نتحقق من مثال:

هنا لديك Homeمكون يولد رقمًا سحريًا كل 1000 مللي ثانية ويضبطه على رقم خاص به state.

بعد ذلك يتم عرض الرقم واستدعاء ثلاثة Childمكونات (أشقاء) ستحصل على الرقم السحري بهدف عرضه باستخدام ثلاث طرق مختلفة:

النهج الأول

ChildOfHomeيحترم المكوِّن تدفق تسلسل خاص بـ React ، وبالنظر إلى أن الهدف هو إظهار الرقم السحري فقط ، فإنه يجعل propsالمستلم مباشرة.

النهج الثاني

ChildOfHomeBrotherيستقبل المكون ال propsمن أصله ويقوم ، باستدعاء componentDidMount، بتعيين الرقم السحري فيه state. ثم يجعل ملف state.magicNumber.

هذا المثال لا يعمل لأنه render()لا يعرف أن a prop قد تغير ، لذا فهو لا يؤدي إلى إعادة عرض المكون. نظرًا لعدم إعادة تقديم المكون بعد الآن ، componentDidMountلا يتم استدعاءه ولا يتم تحديث العرض.

النهج الثالث

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

في هذا الأسلوب الثالث أضفنا componentDidUpdateللتحقق مما إذا كان هناك تغيير propsلبدء إعادة عرض المكون. هذا غير ضروري ويقودنا إلى تعليمات برمجية غير نظيفة. كما أنه يجلب معه تكاليف أداء تتضاعف بعدد المرات التي نقوم فيها بذلك في تطبيق كبير حيث لدينا الكثير من المكونات المتسلسلة والآثار الجانبية.

هذا خطأ ما لم تحتاج إلى السماح للمستخدم بتغيير قيمة الدعامة المستلمة.

إذا لم تكن بحاجة إلى تغيير قيمة prop ، فحاول دائمًا إبقاء الأشياء تعمل وفقًا لتدفق React (النهج الأول).

يمكنك التحقق من صفحة ويب تعمل باستخدام هذا المثال الذي أعددته لك في Glitch. ألقي نظرة واستمتع؟

تحقق أيضًا من الكود الموجود في Home.jsو HomeCodeCleaned.js(بدون عناصر HTML) في الريبو الخاص بي حول هذه المقالة.

كيفية ضبط الحالة

لذا في هذه المرحلة ، أعتقد أن الوقت قد حان لتتسخ أيدينا!

دعنا نلعب قليلاً setStateونحسن ذلك! فقط تابع معنا واحضر كوبًا آخر من القهوة!

لنقم بإنشاء نموذج صغير لتحديث بيانات المستخدم:

فيما يلي رمز المثال أعلاه:

نحن نضع stateككائن ، ولا توجد مشكلة لأن حالتنا الحالية لا تعتمد على حالتنا الأخيرة.

ماذا لو أنشأنا حقل نموذج آخر لتقديم وعرض اسم العائلة؟

لطيف! لقد قمنا بتلخيص handleFormChangeالطريقة لنكون قادرين على التعامل مع جميع حقول الإدخال و setState.

ماذا لو أضفنا زر تبديل لتمييز البيانات على أنها صالحة أو غير صالحة وعدادًا لمعرفة عدد التغييرات التي أجريناها على الحالة؟

بلى! نحن نتأرجح! لقد استخلصنا الكثير من الأشياء!

هممم ... دعنا نقول أنني لا أريد مربع اختيار للتحكم في isValidالمتغير ولكن زر تبديل بسيط.

لنفصل أيضًا معالج العداد عن هذه الطريقة. إنها تعمل بشكل جيد ، ولكن في المواقف الأكثر تعقيدًا حيث تحتاج React إلى إجراء تغييرات مجمعة / مجمعة ، ليس من الجيد الاعتماد على this.state.counterالمتغير لإضافة متغير آخر. يمكن أن تتغير هذه القيمة دون أن تكون على علم بها.

نحن نستخدم نسخة سطحية منها في اللحظة التي يتم فيها استدعاء العملية ، وفي تلك المرحلة المحددة من الوقت لا تعرف ما إذا كانت قيمتها هي القيمة التي كنت تتوقعها أم لا!

دعنا نذهب قليلا العملية!

حسنًا - لقد فقدنا التجريد لأننا فصلنا المعالجات ، لكن هذا لسبب وجيه!

لذلك في هذا الوقت نحتفظ handleFormChangeبتمرير كائن إلى setStateطريقة API. ولكن handleCounterو handleIsValidسائل الآن وظيفي وتبدأ من خلال الاستيلاء على الحالة الراهنة وبعد ذلك، اعتمادا على تلك الدولة، تغييره إلى المرحلة التالية.

هذه هي الطريقة الصحيحة لتغيير stateالمتغيرات التي تعتمد على الحالة السابقة.

ما إذا كنا نريد أن console.log()التغييرات حالة firstNameو lastNameأشكال الإدخال في كل مرة يحدث التغيير؟ دعنا نعطيها محاولة!

لطيف! في كل مرة handleFormChangeيحدث فيها (مما يعني حدوث ضغط مفتاح جديد) logFields()يتم استدعاء الطريقة وتسجيل الحالة الحالية في وحدة التحكم!

دعنا نتحقق من وحدة تحكم المتصفح:

انتظر! ماذا حدث هنا يا رفاق؟ سجل وحدة التحكم هو تغيير واحد قبل إدخال النموذج الحالي! لماذا يحدث هذا؟

setState غير متزامن !!

لقد عرفنا هذا بالفعل ولكننا نراه الآن بأعيننا! ما يحدث هناك؟ دعونا نلقي نظرة على handleFormChangeو logFieldsسائل أعلاه.

لذا فإن handleFormChangeالطريقة تتلقى اسم الحدث وقيمته ، ثم تقوم بجزء setStateمن هذه البيانات. ثم يستدعي handleCounterلتحديث معلومات العداد ، وفي النهاية يستدعي logFieldsالطريقة. logFieldsتأخذ هذه الطريقة في currentStateوتعيد "Eduard" بدلاً من "Eduardo".

الشيء هو: setStateغير متزامن ولا يعمل في الوقت الحالي. تقوم React بعملها وتنفذ logFieldsالطريقة أولاً ، تاركةً setStateحلقة الحدث التالية.

لكن كيف يمكننا تجنب هذا النوع من المواقف؟

حسنًا ، لدى setStateAPI callbackلتجنب هذا الموقف:

إذا أردنا logFields()أن تأخذ في الاعتبار التغييرات الأخيرة التي أجريناها على الحالة ، فنحن بحاجة إلى استدعائها داخل رد الاتصال ، مثل هذا:

حسنًا ، إنه يعمل الآن!

نحن نقول لـ React: "Hey React! احذر من أنه عندما تستدعي logFieldsالطريقة أريدك أن تكون stateمحدثًا بالفعل ، حسنًا؟ أنا أثق بك!"

رد فعل يقول: "حسنًا إيدو! سأقوم بمعالجة كل هذه المجموعة من الأشياء التي أقوم بها عادةً في الفناء الخلفي مع الأشياء setStateوفقط عندما أنتهي من ذلك سأستدعي logFields()! رائع يا رجل! الاسترخاء!"

وفي واقع الأمر - لقد نجحت!

حسنًا جميعًا! بحلول هذا الوقت تعاملنا مع المزالق الرئيسية لـ setState.

هل لديك الشجاعة لتجاوز الجدار؟ احصل على فنجان من القهوة ودعنا نتحلى حقًا ...

الهوى مع setState ()

الآن أن لدينا handleCounterو handleIsValidالأساليب، و setState()أعرب عن وظائف، يمكننا أن يؤلف التحديث الدولة مع وظائف أخرى! تكوين Me likez! دعنا نمرح!

يمكننا أن نأخذ المنطق الداخلي setStateإلى دالة خارج مكون الصنف. دعنا نسميها toggleIsValid. ☝️

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

ماذا لو استخدمنا دالة ترتيب أعلى؟

نجاح باهر! الآن نحن لا نستدعي toggleIsValidالوظيفة بعد الآن. نحن نستدعي دالة مجردة ذات ترتيب أعلى تسمى toggleKeyونمرر مفتاحًا (سلسلة في هذه الحالة) إليها.

كيف نحتاج لتغيير toggleIsValidالوظيفة الآن؟

ماذا؟! الآن لدينا وظيفة تسمى toggleKeyتستقبل a keyوتعيد وظيفة جديدة تغير الحالة وفقًا للمفتاح المزود.

toggleKeyيمكن أن يكون هذا في مكتبة أو في ملف مساعد. يمكن استدعاؤها في العديد من السياقات المختلفة لتغيير حالة كل ما تريد إلى نقيضه.

عظيم!

لنفعل الشيء نفسه مع معالج عداد الزيادة:

بلى! إنها تعمل! لطيف جدا. لنكن مجنون الآن ...

اطلاق النار على القمر والعودة

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

طيب هذا يكفي ... دعنا نتوقف هنا. ؟

يمكنك التحقق من جميع الكود الذي قمنا به في GitHub repo.

اخيرا وليس اخرا

لا تنسَ تجنب استخدام الحالة القصوى واحترام تتالي عرض الدعائم في React.

لا تنسى setStateغير متزامن.

لا تنسى setStateأن تأخذ شيئًا أو وظيفة

لا تنس أنه يجب عليك تمرير وظيفة عندما تعتمد حالتك التالية على حالتك السابقة.

فهرس

  1. توثيق رد الفعل
  2. الوصول إلى الدورات التدريبية التقنية من قبل Ryan Florence ، والتي أوصي بها حقًا.

شكرا جزيلا!