javascript - ماهو - react ترجمة




لماذا استخدام Redux على Facebook Flux؟ (6)

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

كما فهمت ، توفر الدوافع الرسمية لنسخة مستنسخة إيجابيات مقارنة بنيات MVC التقليدية. لكنه لا يقدم إجابة على السؤال:

لماذا يجب عليك استخدام Redux عبر Facebook Flux؟

هل هذا مجرد مسألة أساليب البرمجة: وظيفية مقابل غير وظيفية؟ أو السؤال هو في القدرات / أدوات ديف التي تتبع نهج الإعادة؟ ربما التحجيم؟ أو اختبار؟

هل أنا على صواب إذا قلت أن الإعادة هي تدفق للأشخاص الذين ينتمون إلى لغات وظيفية؟

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

فيما يلي نقاط التحفيز من الدوافع الرسمية لنسخة مسترجع :

  1. التعامل مع التحديثات المتفائلة ( كما فهمت ، لا يكاد يعتمد على النقطة الخامسة. هل من الصعب تنفيذها في facebook flux؟ )
  2. التقديم على الخادم (يمكن لـ facebook flux أيضًا القيام بذلك. أي مزايا مقارنة بإعادة التكرار؟ )
  3. جلب البيانات قبل إجراء انتقالات المسار ( لماذا لا يمكن تحقيق ذلك في تدفق Facebook؟ ما هي الفوائد؟ )
  4. إعادة التحميل الساخنة ( من الممكن مع React Hot Reload . لماذا نحتاج إلى إعادة التشغيل؟ )
  5. تراجع / الإعادة وظيفة
  6. لديك نقاط أخرى؟ مثل استمرار الدولة ...

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

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

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

لقد قررنا أن المضي قدمًا سننتقل إلى Redux وأقترح عليك أن تفعل الشيء نفسه ؛)


استرجاع المؤلف هنا!

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

لا يوجد اختلاف أساسي في Redux ، لكنني أجد أنه يجعل بعض التجريدات أسهل ، أو على الأقل ممكن تنفيذها ، سيكون من الصعب أو المستحيل تنفيذها في Flux.

تكوين المخفض

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

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

يتيح هذا النمط أيضًا ميزات رائعة مثل undo/redo رمز المستخدم. هل يمكنك تخيل توصيل التراجع / الإعادة في تطبيق Flux كونه سطرين من التعليمات البرمجية؟ بالكاد. مع Redux ، يكون الأمر كذلك ، بفضل نمط تكوين المخفض. أحتاج إلى تسليط الضوء على أنه لا يوجد شيء جديد حوله - هذا هو النمط الرائد الذي تم وصفه بالتفصيل في هندسة Elm التي تأثرت هي نفسها بالتدفق.

تقديم الخادم

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

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

لا تزال هناك المشكلات التالية التي تحتاج إلى حلها في Flux (إما بنفسك أو بمساعدة مكتبة Flux المفضلة لديك مثل Flummox أو Alt ):

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

من المسلم به أن أطر Flux (وليس vanilla Flux) لها حلول لهذه المشكلات ، لكني أجدها معقدة للغاية. على سبيل المثال ، يطلب منك Flummox تطبيق sequize serialize() وإلغاء serialize() متاجرك . البديل يحل هذا ألطف من خلال توفير takeSnapshot() الذي يقوم بتسلسل حالتك تلقائيًا في شجرة JSON.

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

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

تجربة المطور

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

لم أر مكتبة Flux واحدة قادرة على القيام بذلك. React Hot Loader أيضًا لا يسمح لك بالقيام بذلك - في الواقع ، تنكسر إذا قمت بتحرير متاجر Flux لأنها لا تعرف ماذا تفعل بها.

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

النظام البيئي

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

بساطة

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

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

على عكس معظم مكتبات Flux ، فإن واجهة Redux API صغيرة للغاية. إذا قمت بإزالة تحذيرات المطورين وتعليقاتهم وفحوصات التعقل ، فسيكون ذلك 99 سطرًا . لا يوجد رمز مزامنة صعب لتصحيح.

يمكنك في الواقع قراءتها وفهم كل من Redux.

انظر أيضًا إجابتي على الجوانب السلبية لاستخدام Redux مقارنةً بـ Flux .


من الأفضل أن تبدأ بقراءة هذا المنشور بواسطة Dan Abramov حيث يناقش العديد من تطبيقات Flux ومبادلاتها في الوقت الذي كان يكتب فيه redux: The Evolution of Flux Frameworks

ثانياً ، لا تناقش صفحة الدوافع التي تربطك بها دوافع Redux فعلاً مثل الدوافع الكامنة وراء Flux (و React). المبادئ الثلاثة أكثر تحديدًا لـ Redux رغم أنها لا تتعامل مع اختلافات التنفيذ من بنية Flux القياسية.

في الأساس ، يحتوي Flux على متاجر متعددة تحسب تغير الحالة استجابة لتفاعلات واجهة المستخدم / واجهة برمجة التطبيقات مع المكونات وتبث هذه التغييرات كأحداث يمكن للمكونات الاشتراك فيها. في Redux ، يوجد متجر واحد فقط يشترك فيه كل مكون. IMO تشعر أنها على الأقل مثل Redux يعمل على زيادة تبسيط وتوحيد تدفق البيانات عن طريق توحيد (أو تقليل ، كما يقول Redux) تدفق البيانات إلى المكونات - في حين يركز Flux على توحيد الجانب الآخر من تدفق البيانات - عرض نموذج.


من تبني رد فعل / استرجاع جديد يهاجر من (بضع سنوات من) ExtJS في منتصف 2018:

بعد الانزلاق للخلف إلى أسفل منحنى التعلم المتكرر ، كان لدي نفس السؤال وأعتقد أن التمويه النقي سيكون أكثر بساطة مثل OP.

سرعان ما رأيت فوائد redux over flux كما هو موضح في الإجابات أعلاه ، وكنت أعمل على تطبيقي الأول.

أثناء الحصول على قبضة على لوحة الغلاية مرة أخرى ، جربت عددًا قليلاً من libs إدارة الدولة الأخرى ، وأفضل ما وجدته هو rematch .

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

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

لذلك بالنسبة لأي شخص آخر وصل إلى هذا المنشور SO يبحث عن "استرجاع أبسط" ، فإنني أوصي بتجربته كبديل بسيط للإعادة مع جميع الفوائد و 1/4 من النمطي.



في قورة ، يقول شخص ما :

بادئ ذي بدء ، من الممكن تمامًا كتابة التطبيقات باستخدام React دون Flux.

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

ولكن إذا كنت لا تزال مهتمًا بمعرفة المزيد ، فاقرأ.

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

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

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

من مستندات Redux :

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

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

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

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

في خطى Flux و CQRS و Event Sourcing ، تحاول Redux جعل طفرات الحالة قابلة للتنبؤ من خلال فرض قيود معينة على كيفية حدوث التحديثات ومتى. تنعكس هذه القيود في المبادئ الثلاثة لـ Redux.

أيضًا من مستندات Redux :

المفاهيم الأساسية
الإعادة نفسها بسيطة جدا.

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

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

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

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

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

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

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter;
  } else {
    return state;
  }
}

function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    return state.concat([{ text: action.text, completed: false }]);
  case 'TOGGLE_TODO':
    return state.map((todo, index) =>
      action.index === index ?
        { text: todo.text, completed: !todo.completed } :
        todo
   )
  default:
    return state;
  }
}

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

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  };
}

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





redux