Redux: سلسلة Redux screencast على Egghead

تم إنشاؤها على ٢٤ نوفمبر ٢٠١٥  ·  69تعليقات  ·  مصدر: reduxjs/redux

إذا كنت تتابع Redux repo ولكنك لم تغوص فيه بعد ، أو كنت مرتبكًا بشأن بعض جوانبه الأساسية ، فسوف يسعدك معرفة أن Egghead قد نشر للتو سلسلة Getting Started with Redux الخاصة بي .

إنه يغطي نفس الموضوعات مثل جزء "الأساسيات" من المستندات ، ولكن نأمل أن يتعمق قليلاً ويضمن لك فهم أساسيات Redux.

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

feedback wanted

التعليق الأكثر فائدة

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

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

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

لا يوجد فرق في طبقة واجهة المستخدم سواء أرسل "المعالج" دالة (يتم التعامل معها بواسطة البرامج الوسيطة) أو ما إذا كان ينفذ استدعاء غير متزامن و _ ثم يرسل إجراءً عاديًا --- واجهة المستخدم غير مقيدة تمامًا (أو على الأقل ، _يمكن_ أن يكون محايدًا)

يوجد جزء كبير من "تطبيقك" في هذه "المعالجات" سواء كنت تستخدم thunks أم لا. في تطبيق رد الفعل / الإعادة النموذجي ، غالبًا ما يكون هؤلاء "المعالجات" منشئو الإجراءات من نوع ما. يمكنك كتابة كل ما تبذلونه من الأشياء غير المتزامنة مثل thunks ، وإرسالها. أو يمكنك كتابة جميع العناصر غير المتزامنة كوظائف تقبل dispatch كوسيطة. من منظور المكون ، يكون إما someHandler(dispatch) أو dispatch(someHandler()) ، أو في حالة تمرير مُنشئي الإجراءات الملزمة من أعلى إلى أعلى ، فهو someHandler() في كلتا الحالتين. يمكنك إنشاء نسخة من bindActionCreators تخفي هذا الاختلاف تمامًا عن طبقة واجهة المستخدم.

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

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

أنا أقدر المناقشة ، وآمل ألا أكون سلبيًا.

ال 69 كومينتر

: +1:

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

: +1:

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

سيكون من الرائع معرفة أفكارك حول هذا.

قد يربك وضع غير قابل للتغيير في هذا المزيج المبتدئين الذين يحتاجون إلى تعلم كيفية التمييز بين Redux و Immutable API ، وقد يفترض أن Immutable مطلوب ، وما إلى ذلك. إنها فكرة جيدة لبضعة دروس متقدمة على الرغم من ذلك!

قد يربك وضع غير قابل للتغيير في هذا المزيج المبتدئين الذين يحتاجون إلى تعلم كيفية التمييز بين Redux و Immutable API ، وقد يفترض أن Immutable مطلوب ، وما إلى ذلك. إنها فكرة جيدة لبضعة دروس متقدمة على الرغم من ذلك!

حسنًا ، هذا منطقي. من الجيد معرفة تفكيرك وراء هذا القرار :-).

ماذا قال smashercosmo : +1:

وحدة التجارب. TDD.

ماذا قال cateland : +1:

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

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

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

أحسنت بشكل ملحوظ ، استمر في ذلك! :)

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

هذا جيد جدا.

العنصر 3 في قائمة smashercosmo هو شيء أود معرفته أيضًا.

ماذا قال @ wpannell ! اختبار الوحدة / TDD!

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

ما الذي تهتم به على وجه التحديد فيما يتعلق باختبار الوحدة؟
تعطي الدروس 5 و 11 و 12 فكرة عن كيفية اختبار وحدة التروس.

... هذا سؤال جيد. هل ستتغير العملية كثيرًا عندما تكون اختبارات المخاوي؟

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

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

نعم ، أعتقد أنه ليس كثيرًا بخلاف تغليف expect s في اختبارات المخاوي. :ممتاز:

الحمد لله كل شيء بسيط جدا!

الثبات مع تجزئات معرف الكائن (على سبيل المثال [post._id]: {...post} ).

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

تضمين التغريدة

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

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

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

أود أيضًا تكوين مخفض متقدم.

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

شاهدت كل شيء ، جيد جدا! أنا أقدر استخدام بناء جملة ES6 / 7 ( Object.assign -like) ، ومكونات دالة React 0.14 وتجنب الأشياء غير القابلة للتغيير.

ربما مقطع فيديو يشرح بنية الكود الموصى بها.

وتحديث المستند لاستخدام صيغ ES6 / 7؟ (هل العلاقات العامة مرحب بها في هذا الاتجاه؟)

اختبار الوحدة ، وإنشاء برمجية API Middleware ، وإجراء OAuth / نوع من مصادقة المستخدم مع Redux ، واستخدام Immutable مع redux (كيفية إعداده ، وأفضل الممارسات ، وما إلى ذلك)

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

gaearon ما رأيك في هيكلة الإجراءات في كمعيار متمني { type: string, payload: Object } منذ البداية؟ أنا أتحدث عن مثال قائمة العداد ، حيث يتم وضع الحمولة على كائن الإجراء نفسه ؛ { type: string, index: number } . هذا يبدو وكأنه مضاد للنمط بالنسبة لي.

ما رأيك في هيكلة الإجراءات في أمثلة مقاطع الفيديو كمعيار متمني {type: string، payload: Object} منذ البداية؟ أنا أتحدث عن مثال قائمة العداد ، حيث يتم وضع الحمولة على كائن الإجراء نفسه ؛ {type: string، index: number}. هذا يبدو وكأنه مضاد للنمط بالنسبة لي.

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

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

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

gaearon حسنًا ، أنا معك بعد ذلك ، على أمل ألا يجعل أولئك الذين اعتادوا على النهج البسيط غير

تضمين التغريدة

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

أيضًا ، لا يوجد شيء غير منظم على الإطلاق بشأن عدم اتباع الجيش السوري الحر. { type: 'STUFF', id: 1 } ليس أسوأ بطبيعته من { type: 'STUFF', payload: { id: 1 } } . إنها مجرد مسألة ذوق و (أحيانًا) اتفاقية أدوات. لا يجعل الحفاظ على كائنات العمل أقل من payload صعوبة في العمل معها.

لدينا عدد قليل من دروس اختبار وحدة الاستعادة التي ستصدر قريبًا على egghead 😄

لقد قمنا بتعليق أي دروس حول Redux لبعض الوقت حتى يحصل Dan على الكراك الأول. يستحق الانتظار ، ثم بعض.

سيكون "إنشاء تطبيق باستخدام Idiomatic Redux" دورة متقدمة رائعة 👍

joelhooks كلاهما يبدو مذهلاً!

أود أن أراك تقوم بإعداد مشروع باستخدام حزمة الويب وإعادة التحميل السريع بدلاً من استخدام jsbin. خذ هذا إلى العالم الحقيقي. أعلم أن الأمر ليس خاصًا بالإعادة ولكني أعتقد أنه سيكون مناسبًا تمامًا وأنت الرجل المناسب لتعليم هذا :)

kevinrenskers انها ليست سلسلة الفيديو، ولكن إذا كنت أشعر بأن تشريح شيء، هناك هم بضعة سبيل المثال boilerplates كبيرة حقا يمكنك الرجوع!

أولئك الذين طلبوا هيكل مشروع لمثال دان وتكوين Webpack.

يرجى التحقق من ذلك https://github.com/urbanvikingr/todo.

لقد التزمت بتحديث Redux باستخدام React doc ليتماشى مع كود Dan من مقاطع الفيديو. سيتم الانتهاء منه في غضون الأسبوعين المقبلين - مشروع العطلة الخاص بي :) - ترقبوا ذلك.

قائمة أمنياتي لمقاطع فيديو Egghead.io:
اختبار العمل / المخفض بالياسمين
الغوص العميق في البرمجيات الوسيطة (thunk / وعود)

تعد لقطات الشاشة مقدمة مفيدة جدًا لـ Redux. ما أود سماعه هو طريقة إعادة التوجيه للقيام بالتوجيه والتقديم من جانب الخادم

grigio قد تكون مهتمًا بهذه المناقشة https://github.com/rackt/redux/issues/1145 حول التوجيه

urbanvikingr شكرا ، اشترك. يبدو أن الاستطلاع مغلقًا ، لكنني كنت سأصوت # 1168

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

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

سأكون أفضل في التحدث باللغة الإنجليزية في نهاية المطاف. في الوقت الحالي ، هذا هو أفضل ما يمكنني فعله ؛-)

gaearon لقد قمت بعمل جيد جدًا في شرح إعادة التشغيل. مجد لك ولإنجازاتك مفتوحة المصدر.

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

(لا تستمع أيضًا إلى jugimaster ، فليس كل شخص يتشتت الحديث عنها" ، أو حتى يهتم بأن لديك لكنة.)

تضمين التغريدة
بالمناسبة ، إنها ليست لهجة :)

لم أكن "أهتم" أيضًا ، لكنني متأكد من تشتيت انتباهي!

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

مرحبًا gaearon ،

بالتأكيد أحب دورتك. عمل جيد! كانت مفيدة جدا.

لقد أضفت ثلاثة دروس فيديو لاختبار Redux إلى دورة Egghead الأخيرة:
https://egghead.io/series/react-testing-cookbook

آمل أن يكونوا مكملين لكل العمل الرائع الذي قمت به!

بالطبع صلبة!

يحسن ليس فقط معرفة الإحياء ولكن المعرفة بالممارسات الحديثة بشكل عام! استمر في فعل أشياء جيدة: +1:: tada:

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

تتوفر مقتطفات التعليمات البرمجية لكل درس لمشتركي Egghead. :-)
مقاطع الفيديو مجانية ولكن يجب على النظام الأساسي جني الأموال حتى يتمكن من الاستثمار في المزيد من الدورات التدريبية ، وإرسال المعدات إلى المدربين ، واستضافة مقاطع الفيديو ، وتحسين موقع الويب ، وما إلى ذلك.

ومع ذلك ، لدينا مجلد examples/todos يتطابق إلى حد كبير مع الدورة التدريبية.

... رائع ، أنا في عداد المفقودين بعد ذلك؟ البحث عن ارتباط (روابط) ...

gaearon يعتذر ، فقط

بالمناسبة ، اشتكى عدد قليل من الأشخاص من عدم دقة النصوص.
يرجى إرسال العلاقات العامة لإصلاحها: https://github.com/eggheadio/egghead-redux-transcripts

gaearon قررت استخدام redux ، ثم وجدت redux vids على egghead. ساعدتني مقاطع الفيديو حقًا في البدء في تعلم إعادة. للمضي قدمًا ، سيكون من الرائع رؤية المزيد من أمثلة العالم الواقعي.

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

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

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

إليك بعض الأمثلة على الكود:

/* actions.js */
// ...
export const USER_MOVE_COLUMN = 'USER_MOVE_COLUMN'

export function userMoveColumn (columnIndex, moveToIndex) {
  return {
    type: USER_MOVE_COLUMN,
    columnIndex,
    moveToIndex
  }
}

export const DATA_TABLE_MOVE_COLUMN = 'DATA_TABLE_MOVE_COLUMN'
// ...

/* reducers.js */
// ...
export default function user (state=userInitialState, action) {
  switch (action.type) {
    // ...
    case USER_MOVE_COLUMN:
      return dataTable(state, assign(
        action,
        {type: DATA_TABLE_MOVE_COLUMN}
      ))
    // ...
    default:
      return state
  }
}
// ...
export default function dataTable (
  state=dataTableInitialState,
  action,
  key='dataTable')
{
  switch (action.type) {
    // ...
    case DATA_TABLE_MOVE_COLUMN:
      return {
        ...state,
        [key]: {
          ...state[key],
          columns: move(
            state[key].columns, action.columnIndex, action.moveToIndex
          )
        }
      }
    // ...
    default:
      return state
  }
}

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

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

آمل أن يكون ذلك مفيدًا وليس مطولًا جدًا. محاولة إعطاء ملاحظات واضحة وصادقة.

لأي روح طيبة قد تساعدني ، لقد وجدت بالفعل /examples/real-world/reducers من تعليقات Dan أخرى وأنا حاليًا أقوم بإعادة صياغة بعض المشكلات التي أشرت إليها أعلاه. لا أريدك أن تضيع الوقت في محاولة المساعدة إذا وجدت حلاً.

شكرا على التنبيه :)

كان دمج أدوات redux-devtools في مشروعي بمثابة ألم كبير بالنسبة لي .. كنت سأقدر (وما زلت سأقدر) سلسلة egghead التي تصف ما هو موجود وكيف / متى أستخدمه. لقد قرأت العلاقات العامة حيث تصف متى تستخدم ماذا .. لكنني مرتبك جدًا هناك الكثير من الأشياء هناك hmr ، التحويل 3 ، redux hot reloader يختلف عن رد فعل إعادة التحميل الساخن وما إلى ذلك ..

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

@ granteagon أليس هذا

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

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

تضمين التغريدة

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

const counterReducersA = {
  // this counter increments by 1 each time
  increment: (state, action) => state + 1
}

const counterReducersB = {
  // this counter increments by 2 each time
  increment: (state, action) => state + 2
}

const counterA = reduxr(counterReducersA, 0);
const counterB = reduxr(counterReducersB, 0);

const rootReducer = combineReducers({
  counterA: counterA.reducer,
  counterB: counterB.reducer
});

store.dispatch(counterA.action.increment());  // increments both counters

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

ربما أساء فهم ما تعنيه بالاقتران ،

أعتقد أن إظهار تدفق غير متزامن بدون برمجيات وسيطة قبل إظهار تنفيذ thunk قد يكون مفيدًا.

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

battaile : هذا لأنه صحيح :) بدون البرامج الوسيطة ، يجب أن يحدث أي عدم التزامن تمامًا خارج Redux (لذلك ، على الأرجح في طبقة واجهة المستخدم الخاصة بك ، مثل مكونات React). في أي وقت تتصل فيه بـ store.dispatch ، سينتقل الإجراء مباشرة إلى وظيفة المخفض ، لا تمر Go ، لا تجمع 200 دولار ، لا تتوقف على طول الطريق لمكالمات AJAX.

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

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

هذا لأنه صحيح :)

لم أقل أنه خطأ ، قلت إنه أبعدني عن المسار :)

أردت فقط أن أفعل شيئًا مثل ما يلي ، والذي بدا أنه يعني أنني لا أستطيع:

const mapDispatchToProps = (dispatch) => ({
  onclick(searchTerm) {
    dispatch(actions.requestOrders(searchTerm));

    return fetch('http://localhost:49984/Order/Search?search=' + searchTerm)
      .then(response => response.json()).then(response => {
        dispatch(actions.receiveOrders(searchTerm, response));
      })
      .catch((err) => {
        dispatch(actions.receiveOrdersError('An error occurred during search: ' + err.message));
      });
  },
});

أدرك أن هذا يمكن أن يصبح قبيحًا بسهولة ، لكن من الناحية المفاهيمية أعتقد أنه من المفيد رؤيته. أو على الأقل كان ذلك في حالتي.

أوافق على أنه "بدون البرامج الوسيطة ، يدعم متجر Redux تدفق البيانات المتزامن فقط." أمر مضلل.

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

نعم ، الاختلاف هو أن السلوك غير المتزامن يحدث تقنيًا بشكل أكبر على مستوى المكون ، وليس "داخل" dispatch . تمييز طفيف ولكنه صالح.

لا أعتقد أن أي شخص يجادل في الواقع بأن العبارة ليست صحيحة من الناحية الفنية.

markerikson فضولي فقط إذا كان لديك أي أمثلة ملموسة حيث يكون التمييز بين الداخل والخارج

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

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

هذه في الواقع جزء كبير من النقطة التي كنت أحاول طرحها في مناقشة Reddit في وقت سابق اليوم: https://www.reddit.com/r/reactjs/comments/4spbip/has_anyone_inserted_a_controllerpresenter_layer/ .

سؤال "ما هي الإجراءات التي أرسلها ومتى أرسلها؟" هو جزء أساسي من منطق عملك ، والنصف الآخر هو "كيف يمكنني تحديث حالتي استجابةً لتلك الإجراءات؟". إذا كانت إدارة الإجراء في thunks and sagas وما إلى ذلك ، فلا يهم حقًا ما إذا كان هذا الرمز قد تم تشغيله بواسطة مكون React أو وحدة تحكم Angular أو معالج نقر jQuery أو مثيل مكون Vue أو أي شيء آخر. منطقك الأساسي خارج طبقة واجهة المستخدم ، وطبقة واجهة المستخدم مسؤولة حقًا فقط عن سحب البيانات التي تحتاجها من المتجر ، وعرضها ، وتحويل مدخلات المستخدم إلى استدعاء وظيفة منطقية للتطبيق.

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

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

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

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

لا يوجد فرق في طبقة واجهة المستخدم سواء أرسل "المعالج" دالة (يتم التعامل معها بواسطة البرامج الوسيطة) أو ما إذا كان ينفذ استدعاء غير متزامن و _ ثم يرسل إجراءً عاديًا --- واجهة المستخدم غير مقيدة تمامًا (أو على الأقل ، _يمكن_ أن يكون محايدًا)

يوجد جزء كبير من "تطبيقك" في هذه "المعالجات" سواء كنت تستخدم thunks أم لا. في تطبيق رد الفعل / الإعادة النموذجي ، غالبًا ما يكون هؤلاء "المعالجات" منشئو الإجراءات من نوع ما. يمكنك كتابة كل ما تبذلونه من الأشياء غير المتزامنة مثل thunks ، وإرسالها. أو يمكنك كتابة جميع العناصر غير المتزامنة كوظائف تقبل dispatch كوسيطة. من منظور المكون ، يكون إما someHandler(dispatch) أو dispatch(someHandler()) ، أو في حالة تمرير مُنشئي الإجراءات الملزمة من أعلى إلى أعلى ، فهو someHandler() في كلتا الحالتين. يمكنك إنشاء نسخة من bindActionCreators تخفي هذا الاختلاف تمامًا عن طبقة واجهة المستخدم.

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

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

أنا أقدر المناقشة ، وآمل ألا أكون سلبيًا.

هذه الدورة رائعة. إغلاق هذا حتى يتمكن الأشخاص من توجيه تعليقاتهم إلى مستودع ملاحظات المجتمع للدورة التدريبية: https://github.com/tayiorbeii/egghead.io_redux_course_notes

تأكد أيضًا من إطلاعك على المسلسل التالي الذي وضعه دان معًا! https://egghead.io/courses/building-react-applications-with-idiomatic-redux

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات