إرشادات عملية لتطوير تطبيقات React على نطاق واسع. الجزء 2: إدارة الدولة ، التوجيه

ننشر اليوم الجزء الثاني من ترجمة المادة ، المكرس لتطوير تطبيقات تفاعلية واسعة النطاق. سنتحدث هنا عن إدارة حالة التطبيقات والتوجيه وتطوير الواجهة.



الجزء 1: المبادئ التوجيهية العملية لتطوير تطبيقات رد الفعل على نطاق واسع. التخطيط والإجراءات ومصادر البيانات وواجهة برمجة التطبيقات

الجزء 2: المبادئ التوجيهية العملية لتطوير تطبيقات رد الفعل على نطاق واسع. الجزء 2: إدارة الدولة ، التوجيه


إدارة حالة التطبيق ، والتكامل Redux ، وتنظيم التوجيه


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

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

tasks حل المهام التي لا يمكن حلها مع وظائف نقية


النظر في السيناريو التالي. لقد عرض عليك العمل على تطبيق مصمم لشركة تعمل في سوق العقارات. يريد العميل الحصول على موقع جديد وأفضل. تحت تصرفك يوجد REST API ، لديك تخطيطات لجميع الصفحات المعدة بمساعدة Zapier ، لقد حددت خطة للتطبيق. ولكن بعد ذلك تسللت مشكلة ضخمة.

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

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

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


تطبيق الرسم البياني باستخدام Redux وإعادة تخزين الملحمة

هنا ، يرسل المكون الإجراء GET.BLOGS . يستخدم التطبيق ميزة الإعادة ، لذلك سيتم اعتراض هذا الطلب. بعد ذلك ، ستقوم وظيفة المولد بتنزيل البيانات من مخزن البيانات في الخلفية وتحديث حالة التطبيق التي يدعمها Redux.

فيما يلي مثال على كيفية ظهور وظيفة المولد لتحميل المنشورات (تسمى هذه الوظائف "sagas") في الحالة الموضحة. يمكن استخدام Sagas في السيناريوهات الأخرى. على سبيل المثال ، لتنظيم تخزين بيانات المستخدم (على سبيل المثال ، يمكن أن يكون رمزًا) ، لأن هذا مثال آخر لمهمة لا تكون الوظائف الخالصة مناسبة لها.

 ... function* fetchPosts(action) { if (action.type === WP_POSTS.LIST.REQUESTED) {   try {     const response = yield call(wpGet, {       model: WP_POSTS.MODEL,       contentType: APPLICATION_JSON,       query: action.payload.query,     });     if (response.error) {       yield put({         type: WP_POSTS.LIST.FAILED,         payload: response.error.response.data.msg,       });       return;         yield put({       type: WP_POSTS.LIST.SUCCESS,       payload: {         posts: response.data,         total: response.headers['x-wp-total'],         query: action.payload.query,       },       view: action.view,     });   } catch (e) {     yield put({ type: WP_POSTS.LIST.FAILED, payload: e.message });  ... 

تتوقع الملحمة المعروضة هنا إجراءات مثل WP_POSTS.LIST.REQUESTED . من خلال تلقي مثل هذا الإجراء ، يقوم بتحميل البيانات من API. هي ، بعد تلقي البيانات ، ترسل إجراءً آخر - WP_POSTS.LIST.SUCCESS . تؤدي معالجته إلى تحديث المستودع باستخدام المخفض المناسب.

▍ مقدمة من المخفضات


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

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

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

أولاً ، دعنا ننظر إلى تكاملها مع Redux:

 ... const withConnect = connect( mapStateToProps, mapDispatchToProps, ); const withReducer = injectReducer({ key: BLOG_VIEW, reducer: blogReducer, }); class BlogPage extends React.Component {  ... } export default compose( withReducer, withConnect, )(BlogPage); 

هذا الرمز هو جزء من ملف BlogPage.js الذي يحتوي على مكون التطبيق.

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

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

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

and التوجيه والإعادة


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

في أغلب الأحيان ، يتم استخدام جهاز توجيه BrowserRouter مثل هذا: يتم تضمين مكون الجذر في علامة BrowserRouter ، ويتم تغليف الحاويات التابعة withRouter() ويتم تصديرها ( هنا مثال).

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

يمكن أن يؤدي خيار التوجيه هذا إلى حدوث مشكلات في التطبيقات الكبيرة. هذا يرجع إلى حقيقة أنه ليس لديهم كائن history مركزي. بالإضافة إلى ذلك ، لا تعمل المكونات التي لم يتم تقديمها باستخدام <Route> مع كائن history . هنا مثال باستخدام <Route> :

 <Route path="/" exact component={HomePage} /> 

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

بعد الانتهاء من تكوينه ، يمكن استخدام نظام التوجيه الجديد من خلال Redux. لذلك ، يمكن تنفيذ التنقل في التطبيق عن طريق إرسال الإجراءات.

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

 import { push } from 'connected-react-router' ... const mapDispatchToProps = dispatch => ({  goTo: payload => {    dispatch(push(payload.path));  }, }); class DemoComponent extends React.Component {  render() {    return (      <Child        onClick={          () => {            this.props.goTo({ path: `/gallery/`});                      />    } ... 

تقوم طريقة goTo هنا بإرسال إجراء يدفع عنوان URL المطلوب goTo حزمة سجل المتصفح. في السابق ، تم goTo طريقة goTo إلى المستودع. لذلك ، يتم تمرير هذه الطريقة إلى DemoComponent في كائن props .

واجهة المستخدم الديناميكية واحتياجات التطبيق المتنامية


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

▍ كسل التحميل و React.Suspense


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

عادة ما يُنظر إلى النظم الفرعية للشبكة على أنها غير موثوقة وعرضة للخطأ.

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

لكن منشئي البرنامج لا يسعون إلى تبرير العمل ذي النوعية الرديئة للتطبيقات بعبارات مثل "هذا ليس من أعمالي". وجدوا طرق مثيرة للاهتمام للتعامل مع مشاكل الشبكة.

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


من الأفضل للمستخدمين عدم رؤية أي شيء مثل هذا.

تتيح لك تقنية React Suspense التعامل مع مثل هذه المشكلات فقط. على سبيل المثال ، يسمح لك بعرض مؤشر معين أثناء تحميل البيانات. على الرغم من أنه يمكن القيام بذلك يدويًا عن طريق تعيين الخاصية isLoaded على true ، فإن استخدام Suspense API يجعل الكود أكثر نظافة.

هنا يمكنك مشاهدة مقطع فيديو جيد حول Suspense ، حيث يقدم Jared Palmer للجمهور هذه التكنولوجيا ويظهر بعض ميزاته باستخدام مثال لتطبيق حقيقي .

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


التطبيق الذي لا يستخدم التشويق

يعد تزويد أحد المكونات بدعم تشويق أسهل بكثير من استخدام isLoaded مستوى isLoaded . لنبدأ بوضع حاوية App الأصل في React.StrictMode . نتأكد من أنه من بين وحدات React المستخدمة في التطبيق ، لن يكون هناك تلك التي تعتبر قديمة.

 <React.Suspense fallback={<Spinner size="large" />}>  <ArtistDetails id={this.props.id}/>  <ArtistTopTracks />  <ArtistAlbums id={this.props.id}/> </React.Suspense> 

المكونات ملفوفة في علامات React.Suspense ، أثناء تحميل المحتوى الرئيسي ، تحميل وعرض ما هو محدد في خاصية fallback . يجب أن نسعى جاهدين للتأكد من أن المكونات المستخدمة في خاصية fallback تحتوي على أصغر حجم ممكن وترتيبها بأبسط ما يمكن.


التطبيق الذي يستخدم التشويق

▍ المكونات التكيفية


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

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

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


عنصر لوصف السيارة وعنصر لوصف المسار

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

إنشاء مكونات مستقلة منفصلة لكل من هذه الكيانات يتعارض مع المنطق السليم.

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


شريط البحث

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

 static propTypes = {  open: PropTypes.bool.isRequired,  setOpen: PropTypes.func.isRequired,  goTo: PropTypes.func.isRequired, }; 

باستخدام هذه التقنية ، يمكنك التحكم في استخدام فئات HTML عند عرض هذه العناصر ، مما يتيح لك التأثير على مظهرها.

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


لوحة ترقيم الصفحات

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

النتائج


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

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

عند التخطيط ، من السهل جدًا فهم الأدوات التي يتم إنشاؤها مباشرة للمشروع والأدوات التي من الواضح أنها غير مناسبة له ، لأنها كبيرة جدًا بالنسبة له. على سبيل المثال ، لا يحتاج التطبيق الذي يتكون من 2-3 صفحات وأداء عدد قليل جدًا من الطلبات إلى بعض واجهات برمجة التطبيقات (APIs) إلى مخازن بيانات مماثلة لتلك التي تحدثنا عنها. أنا مستعد للمضي قدماً في هذه الاعتبارات ، وأقول إنه في المشروعات الصغيرة لا تحتاج إلى استخدام Redux.
في مرحلة التخطيط للتطبيق ، أثناء رسم تخطيطات لصفحاته ، من السهل أن نرى أن العديد من المكونات المشابهة تستخدم في هذه الصفحات. إذا حاولت إعادة استخدام رمز هذه المكونات أو كنت تسعى إلى كتابة مكونات عالمية ، فسيساعد ذلك في توفير الكثير من الوقت والجهد.

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

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

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


All Articles