Redux: أمثلة - كيفية تنفيذ مساحة أسماء نوع الإجراء؟

تم إنشاؤها على ٢٣ سبتمبر ٢٠١٥  ·  32تعليقات  ·  مصدر: reduxjs/redux

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

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

نسيت شيئا ما هنا ؟ يا رفاق ليس لديك اصطدام تسمية نوع العمل؟

هل يمكن لشخص ما تحديث الأمثلة ويوضح لي كيف تتعامل مع هذه المشكلة أو يوجهني في الاتجاه الصحيح؟

تتعلق حالتي المحددة بوجود لوحتين إداريتين منفصلتين في الواجهة الأمامية. واحد للمختبرين والآخر للعملاء الذين سيتم تخزين حالتهم في أقسام منفصلة من المتجر ("testerAccount" ، "customerAccount") ، ولكن كلاهما سيكون قادرًا على القيام بأشياء مماثلة على سبيل المثال ADD_VIDEO_UPLOAD ، ADD_COMMENT ، إلخ ، وما إلى ذلك.

سأكون ممتنًا لمساعدتك هنا :)

question

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

السلاسل ليست سيئة بطبيعتها لمسافات الأسماء. عناوين URL عبارة عن سلاسل ، ويبدو أنها تعمل بشكل جيد.

ال 32 كومينتر

وضع accountType في الإجراءات؟ راجع أيضًا examples/real-world/reducers لمعرفة كيفية كتابة مصنع مخفض واستخدام نفس الرمز عدة مرات لإنتاج مخفضات تستجيب لإجراءات مختلفة.

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

أعتقد أنه سيكون من المفيد حقًا أن تقدم مثالًا صغيرًا محددًا للمشكلة التي تقول أنه تم تجاهلها في الأمثلة الحالية.

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

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

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

أتمنى أن هذا يجعل الأمر أكثر وضوحا.

لقد قمت بحل هذه المشكلة في مشروعي (مشاريعي) باستخدام https://www.npmjs.com/package/flux-constant جنبًا إلى جنب مع وظيفة مساعد بسيطة للغاية تسمى createActionTypes .

بشكل أساسي ، ينتهي الأمر بكود:

// create-action-types.js
var fluxConstant = require('flux-constant');
module.exports = function (types) {
    return fluxConstant.set(types);
};

// in foo-action-types.js
module.exports = createAtionTypes([
    'ADD_FOO',
    'REMOVE_FOO'
]);

// in some-store.js
var fooActionTypes = require('foo-action-types');
function (state, action) {
    switch(action.type) {
        case fooActionTypes.ADD_FOO: 

        case fooActionTypes.REMOVE_FOO:
   }
}

لماذا لا نحتفظ بجميع أنواع الإجراءات كثوابت في مكان واحد؟
ثم من المؤكد أنهم لا يستطيعون الصدام لأنه لا يمكنك تصدير نفس الاسم مرتين.

لتصور هذا بشكل أفضل ، دعنا نقول أن هذه هي الحالة الأولية للمتجر:


let initialState = {
  "testerAccount": {
    "videoUploads": [],
    "messages": []
  },
  "customerAccount": {
    "videoUploads": [],
    "messages": []
  },
  "systemUserAccount": {
    "videoUploads": [],
    "messages": []
  }
};

كيف ستتجنب تضارب اسم نوع الإجراء عند تنفيذ مخفضات منفصلة لإضافة مقاطع فيديو أو رسائل لكل قسم من هذه الأقسام؟

gaearon ما

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

ADD_VIDEO_UPLOAD ، ADD_TESTER_VIDEO_UPLOAD ، ADD_VIDEO_UPLOAD_IN_SOME_SECTION ، إلخ.

وهو صداع كبير مرة أخرى.

koulmomo هذا بالضبط ما كنت أبحث عنه ، شكرًا لك :): +1: بسيط وقوي.

gaearon أعتقد أنه يجب أن يكون لدينا مثال واحد على الأقل يستخدم إما هذه الحزمة أو حزمة جديدة يمكن تسميتها بـ redux-ثابت؟

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

شكرا لكم على مساعدتكم مع هذا :)

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

لا أعتقد أن flux-constant هو حل رائع هنا. يبدو أنه يعتمد على شيكات instanceof . مما يعني أنه لا يمكنك إجراء تسلسل لأفعالك وإعادة تشغيلها لاحقًا لأن - بام! - أنواعها التي تم إلغاء تسلسلها لن تتطابق مع تلك التي تم إنشاؤها.

غالبًا ما يحاول الناس جعل Flux "أبسط" دون إدراك أنهم يكسرون ميزاته الأساسية .

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

لقد كنت مضللاً بالتناسق الواضح في مثالك. أفهم الآن أنك تقصد عدم وجود جفاف هنا ، والتماثل في الميزات واضح فقط كما قلت في https://github.com/rackt/redux/issues/786#issuecomment -142649749.

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

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

أنا جميعًا لإضافة مثال huge-apps مع تقسيم الكود ، وأنواع الإجراءات ذات مساحة الاسم ، وما إلى ذلك ، ستكون هذه مشكلة منفصلة.

السلاسل ليست سيئة بطبيعتها لمسافات الأسماء. عناوين URL عبارة عن سلاسل ، ويبدو أنها تعمل بشكل جيد.

gaearon أنت محق ، لقد نسيت مشكلة التسلسل مع الحل القائم على ثابت التدفق.

ليس لدي مشكلة مع مسافة الأسماء المستندة إلى السلسلة طالما أنه يمكننا بسهولة التمييز بين الوحدات / مساحات الأسماء في الاسم نفسه.

الحل القائم على اصطلاح التسمية هو شيء رأيته من قبل:

https://github.com/erikras/ducks-modular-redux

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

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

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

شكرا مرة اخرى :)

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

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

بقدر ما أستطيع أن أقول ، لا توجد طريقة لتحقيق كل من التسلسل وغياب التعارضات.

قد تستخدم الاصطلاحات الجيدة للوحدات القابلة لإعادة الاستخدام "موفري التفرد" الموجودين بالفعل ، مثل أسماء المجالات العكسية ، أو اسم المستخدم / الريبو على جيثب ، أو اسم الوحدة المسجلة على npm.


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

+1 للسؤال والمناقشة. لقد عانيت أيضًا كثيرًا مع هذه المشكلة بالضبط مثل

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

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

مثال هنا: https://gist.github.com/samsch/63a54e868d7fa2b6023a

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

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

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

لنفترض أن لديك وحدة نمطية "Geometry" ، مع ActionType "Area". تستخدم هذه الوحدة في مكانين:

  1. AppA-> Drawing-> Geometry (namespace = "Drawing / Geometry / Area")
  2. AppB-> علم المثلثات-> الشكل-> الهندسة (مساحة الاسم = "علم المثلثات / الشكل / المنطقة")

لديك الآن مساحة اسم متعارضة ، اعتمادًا على مكان استخدام الوحدة الخاصة بك.

  • إنها ليست فكرة جيدة أن تقوم بتشفير هذا المسار الكامل في وحدة Geometry الخاصة بك لـ ActionType "Area".
  • بدلاً من ذلك ، اجعل الاسم بسيطًا: "المنطقة".
  • بطريقة مماثلة لتكوين المخفض ، قم بتكوين مساحة الاسم من خلال جعل كل أصل يحتوي على إضافة بادئة.

أقوم بتجربة النمط التالي:

قم بإنشاء مسار لكل نوع من المجموعات التي تحتوي على:

  • ثوابت
  • مخفض
  • المكونات
  • الملاحم

إنشاء ثوابت بالتنسيق التالي:

// song-store/song-store-consts.js
export const ADD = 'SONG_STORE.ADD'
export const REMOVE = 'SONG_STORE.REMOVE'

عند استخدام الثوابت في المخفضات أو الملحمة أو الإجراءات import كلهم بـ * :

// song-store/song-store-actions.js
import * as SONG_STORE from './song-store-consts'

export function addSongStore(name) {
  return {
    type: SONG_STORE.ADD,
    name
  }
}

export function removeSongStore(songStoreId) {
  return {
    type: SONG_STORE.REMOVE,
    songStoreId
  }
}

للأسف ليست كبيرة لهز الشجرة. سيكون لطيفًا إذا سمح ES6:

import { ADD, REMOVE } as SONG_STORE from './song-store-actions'

هل يعلم أي شخص ما إذا كان Webpack 2 يمكنه بذكاء تحريك شجرة import * لذلك فهو لا يجمع رمزًا للتصدير الذي لا يتم استخدامه حتى لو تم استيراده بـ * ؟

يبدو أن هذه مشكلة شائعة جدًا وتظهر في كثير من الأحيان في مكتبنا ، إما:

  • تتسبب تعارضات الأسماء في سلوك غير مرغوب فيه.
  • الشكوى من النموذج الأساسي المرتبط بإنشاء أنواع عمل فريدة.

لقد جربنا عددًا قليلاً من الحلول المختلفة ولكن لا يبدو أن هناك شيئًا ثابتًا:

  1. من المؤكد أن
  2. جذبت القيم التي تم إنشاؤها عشوائيًا والتي ذكرها samsch انتباهي حقًا وهي تعمل بالتأكيد ، ولكن نعم ، فإن فقدان الجزء الذي يمكن قراءته من قِبل الإنسان يجعل من الصعب التعايش معه.
  3. لقد أعجبني التعليق أعلاه من philholden حقًا ، حيث نستخدم عادةً بنية مدفوعة

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

مثال

في App/testerAccount/index.js :

// Something like this
const ADD_VIDEO_UPLOAD = `${__filenamespace}/ADD_VIDEO_UPLOAD`;
const ADD_COMMENT = `${__filenamespace}/ADD_COMMENT`;

// Will be transformed into something like this
const ADD_VIDEO_UPLOAD = 'App/testerAccount/ADD_VIDEO_UPLOAD';
const ADD_COMMENT = 'App/testerAccount/ADD_COMMENT';

لا تتردد في تجربته ، وآمل أن يكون مفيدًا. سيكون من الرائع الحصول على أي تعليقات ، خاصةً من pbc أو gaearon بصفتك منشئ المشكلة ومنشئ المكتبة.

https://www.npmjs.com/package/babel-plugin-filenamespace

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

هل سنقوم بعمل "featureName$actionType" أو "fileName/ACTION_TYPE" أو "PROJECT.FEATURE.ACTION" ؟ إذا تمكنا جميعًا من الاتفاق على شيء ما ، فسيكون من الأسهل مشاركة المخفضات.

أعتقد أنه مع ندرة الاتفاقيات الأخرى المتاحة ، أصبح البط هو المعيار الفعلي.

const ACTION = 'app/feature/ACTION'; كافٍ جدًا.

ذكرgaearon دائمًا أن العلاقة 1: 1 بين الإجراءات
على سبيل المثال. يمكن تمكين أو تعطيل تبديل التفضيل البسيط من مكانين مختلفين:
/ myaccount / toggleNotification
/ لوحة القيادة / toggleNotification
لذلك يجب أن يكون لدينا مخفضان مكتوبان بنفس المحتوى بتنسيق
مخفضات / إخطارات.js
نسخة إلى : philholden


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

على أي حال ، أود أن أسمع من الخبراء. شكر.

ivks : عدة أفكار هنا.

أولاً ، يمكنك إرسال نفس الإجراء من أماكن متعددة داخل التطبيق.

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

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

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

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

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

لا أعتقد أن تعريف البط بشكل صحيح في ActionTypes:

يجب أن يكون لديك أنواع الإجراءات في النموذج npm-module-or-app / المخفض / ACTION_TYPE

والسبب هو أنه يمكن الاشتراك في إجراء واحد بواسطة أكثر من مخفضات. كما قال mherodev ، const ACTION = 'app/feature/ACTION'; أكثر منطقية ، بالإضافة إلى ذلك أود إضافة مخطط للعمل: const ACTION = 'action://app/feature/ACTION'; .

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

let id = 0

function generateActionType (label /* for readability */) {
  id++
  return `app/feature/${id}/${label}`
}

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

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

إذا كان هناك أي اقتراح ، فيرجى إبلاغي بذلك :)

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