كيفية تحويل withRouter إلى رد فعل هوك

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

يجب أن تكون هذه المقالة بمثابة برنامج تعليمي لتطبيق ربط React مع وظيفة pub-sub. Pub-sub ، اختصار لـ "publish-subscribe" ، هي منهجية برمجة حيث يتم إخطار مجموعة من عمليات الاشتراك عند نشر التحديث. باختصار ، عندما يتغير الموقع (الحدث المنشور) ، أريد إعادة تقديم المكون الخاص بي (اشتراك المستمع).

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

يمكنك استخدام هذه الحزمة بنفسك عبر استخدام-react-router-router على NPM أو المساهمة في مستودع GitHub مفتوح المصدر أو الشوكة أو التجسس عليه.

تجربة المستخدم

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

لحسن الحظ ، فإن تطبيق withRouter ليس تطبيقًا صعبًا ، لذلك لا يتم ربطه.

أريد استيراد خطاف من تصدير الحزمة الافتراضية.

أريد أن أسمي هذا الخطاف وأن يتم ذلك.

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

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

التطبيق

التبعيات

أولا ، تبعياتنا.

سنحتاج إلى سياق جهاز التوجيه من حزمة جهاز التوجيه ، حيث أنه يحتوي على البيانات التي نريد الوصول إليها في مكوننا ، وسنحتاج إلى ربط خط ربط useContext من حزمة التفاعل إلى "ربط" في سياق جهاز التوجيه. نظرًا لأننا نطبق وظيفة pub-sub ، فنحن نحتاج أيضًا إلى خطاف useEffect المضمن في React. سيسمح لنا ذلك بالاشتراك وإلغاء الاشتراك في تغييرات الموقع.

أخيرًا ، سأقوم باستيراد useForceUpdate من حزمة NPM الخاصة بإستخدام use-force-update. إنه مجرد اختصار للاتصال بخطاب useState لفرض إعادة تقديم ، وهو ما سنفعله عندما يتغير الموقع.

هوك

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

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

إذا كنت لا تريد وظيفة إعادة التقديم ، يمكنك التوقف هنا. يمكنك إزالة متغير forceUpdate ، واستخدام importEffect ، واستخدام اعتماد تحديث القوة. أنصح باستخدام ربط useReactRouter خارجي عبر استدعاء useContext داخل المكون الخاص بك فقط بسبب اسم __RouterContext و @ nvv semvar اللازمة حاليًا للوصول إلى React Router v4.4. قد يكون الوصول إلى هذا السياق عرضة للتغيير ، وجعل إجراء هذا التعديل في الحزمة الفردية أقل بكثير من عمل هذا التعديل في كل مكون يعتمد على جهاز التوجيه الذي تستخدمه في مشروعك. كما أنه من السهل جدًا على المطورين أن يستخدموا ReactRouter من useContext (__ RouterContext) - استيراد السياق الإضافي لا لزوم له ولا يتغير.

حانة الفرعية

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

يستعاض عن / * TODO * / بما يلي:

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

عندما تكون effect1 هي الوظيفة الخارجية و effect2 هي الوظيفة الداخلية ، تنفذ دورة حياة المكون مثل:

جبل> effect1 ... effect2> تحديث> effect1 ... effect2> إلغاء تحميل

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

هدفنا هو الاشتراك في تغييرات الموقع بمجرد تركيب مكون لدينا وإلغاء الاشتراك في تغييرات الموقع قبل إلغاء تثبيت المكون الخاص بنا.

صفيف المذكرة من useEffect يقول "لا تنفذ وظائف التأثير هذه عند التحديث ما لم يتم تغيير هذه المجموعة من المعلمات." يمكننا استخدام هذا للاشتراك بشكل مستمر وإلغاء الاشتراك في تغييرات الموقع لمجرد إعادة تقديم المكون. طالما أن سياق جهاز التوجيه هو نفسه ، نحن لسنا بحاجة إلى تغيير اشتراكنا. لذلك ، يمكن أن تحتوي مجموعة المذكرات لدينا على عنصر واحد: [routerContext].

كيف يمكنك الاشتراك في تغييرات الموقع؟ بتمرير وظيفة إلى routerContext.history.listen ، سيتم تنفيذ هذه الوظيفة في كل مرة يتغير سجل جهاز التوجيه. في هذه الحالة ، فإن الوظيفة التي نريد تنفيذها هي ببساطة تحديث.

وكيف يمكنك إلغاء الاشتراك من تغييرات الموقع؟ لا يمكننا ترك هذا الاشتراك موجودًا بعد إلغاء تثبيت المكون - سيتم استدعاء فرض التحديث ، ولكن لن يكون هناك مكون للتحديث!

routerContext.history.listen تقوم بإرجاع وظيفة إلغاء الاشتراك ، عندما يتم استدعاؤها ، تقوم بإزالة موزع رسائل الاشتراك (forceUpdate) من الحدث.

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

وحتى أقصر:

أين أذهب من هنا؟

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

على الرغم من أنني لم أقم بتسخير ذلك في الحزمة الخاصة بي حتى الآن ، إلا أنني أعتقد أن الخطوة التالية القوية ستكون استخدام الدعائم الخاصة بالمكون المربوط كمعلمة لاستخدام useReactRouter ، مما يتيح لها استخدام نفس أولوية prop.

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

الخاتمة

إذا كنت ترغب في المساهمة في هذه الحزمة مفتوحة المصدر أو تراها في TypeScript ، فيمكنك تمييزها بنجمة أو تفرعها أو فتح المشكلات أو التحقق من ذلك على GitHub. يمكنك استخدام هذه الحزمة بنفسك عبر use-react-router على NPM.

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

لقراءة المزيد من أعمالي ، يمكنك متابعتي على LinkedIn و Twitter ، أو تحقق من ملفي على CharlesStover.com.