Redux-symbiote - كتابة إجراءات ومخفضات بدون أي ألم تقريبًا

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

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

آلام التنفيذ الكلاسيكي


مثال بسيط:

// actionTypes.js //    export const POPUP_OPEN_START = 'POPUP_OPEN_START '; export const POPUP_OPEN_PENDING = 'POPUP_OPEN_PENDING '; export const POPUP_OPEN_SUCCESS = 'POPUP_OPEN_SUCCESS '; export const POPUP_OPEN_FAIL = 'POPUP_OPEN_FAIL'; export const POPUP_CLOSE_START = 'POPUP_CLOSE_START '; export const POPUP_CLOSE_PENDING = 'POPUP_CLOSE_PENDING '; export const POPUP_CLOSE_SUCCESS = 'POPUP_CLOSE_SUCCESS '; export const POPUP_CLOSE_FAIL = 'POPUP_CLOSE_FAIL'; 

 // actions.js //    import { POPUP_OPEN_START, POPUP_OPEN_PENDING, POPUP_OPEN_SUCCESS, POPUP_OPEN_FAIL, POPUP_CLOSE_START, POPUP_CLOSE_PENDING, POPUP_CLOSE_SUCCESS, POPUP_CLOSE_FAIL } from './actionTypes'; export function popupOpenStart(name) { return { type: POPUP_OPEN_START, payload: { name }, } } export function popupOpenPending(name) { return { type: POPUP_OPEN_PENDING, payload: { name }, } } export function popupOpenFail(error) { return { type: POPUP_OPEN_FAIL, payload: { error, }, } } export function popupOpenSuccess(name, data) { return { type: POPUP_OPEN_SUCCESS, payload: { name, data }, } } export function popupCloseStart(name) { return { type: POPUP_CLOSE_START, payload: { name }, } } export function popupClosePending(name) { return { type: POPUP_CLOSE_PENDING, payload: { name }, } } export function popupCloseFail(error) { return { type: POPUP_CLOSE_FAIL, payload: { error, }, } } export function popupCloseSuccess(name) { return { type: POPUP_CLOSE_SUCCESS, payload: { name }, } } 

 // reducers.js //   import { POPUP_OPEN_START, POPUP_OPEN_PENDING, POPUP_OPEN_SUCCESS, POPUP_OPEN_FAIL, POPUP_CLOSE_START, POPUP_CLOSE_PENDING, POPUP_CLOSE_SUCCESS, POPUP_CLOSE_FAIL } from './actionTypes'; const initialState = { opened: [] }; export function popupReducer(state = initialState, action) { switch (action.type) { case POPUP_OPEN_START: case POPUP_OPEN_PENDING: case POPUP_CLOSE_START: case POPUP_CLOSE_PENDING: return { ...state, error: null, loading: true }; case POPUP_OPEN_SUCCESS : return { ...state, loading: false, opened: [ ...(state.opened || []).filter(x => x.name !== action.payload.name), { ...action.payload } ] }; case POPUP_OPEN_FAIL: return { ...state, loading: false, error: action.payload.error }; case POPUP_CLOSE_SUCCESS: return { ...state, loading: false, opened: [ ...state.opened.filter(x => x.name !== name) ] }; case POPUP_CLOSE_FAIL: return { ...state, loading: false, error: action.payload.error }; } return state; } 

الإخراج يحتوي على 3 ملفات والمشاكل التالية على الأقل:

  • "سخام" الكود ببساطة عن طريق إضافة سلسلة جديدة من الإجراءات
  • الاستيراد الزائد من ثوابت العمل
  • أسماء القراءة المستمرة للعمل (بشكل فردي)

التحسين


يمكن تحسين هذا المثال من خلال إجراءات التكرار .

 import { createActions, handleActions, combineActions } from 'redux-actions' export const actions = createActions({ popups: { open: { start: () => ({ loading: true }), pending: () => ({ loading: true }), fail: (error) => ({ loading: false, error }), success: (name, data) => ({ loading: false, name, data }), }, close: { start: () => ({ loading: true }), pending: () => ({ loading: true }), fail: (error) => ({ loading: false, error }), success: (name) => ({ loading: false, name }), }, }, }).popups const initialState = { opened: [] }; export const accountsReducer = handleActions({ [ combineActions( actions.open.start, actions.open.pending, actions.open.success, actions.open.fail, actions.close.start, actions.close.pending, actions.close.success, actions.close.fail ) ]: (state, { payload: { loading } }) => ({ ...state, loading }), [combineActions(actions.open.fail, actions.close.fail)]: (state, { payload: { error } }) => ({ ...state, error }), [actions.open.success]: (state, { payload: { name, data } }) => ({ ...state, error: null, opened: [ ...(state.opened || []).filter(x => x.name !== name), { name, data } ] }), [actions.close.success]: (state, { payload: { name } }) => ({ ...state, error: null, opened: [ ...state.opened.filter(x => x.name !== name) ] }) }, initialState) 

بالفعل أفضل بكثير ، ولكن لا يوجد حد الكمال.

علاج الألم


بحثًا عن حل أفضل ، صادفت تعليقًا لـ LestaD habr.com/en/post/350850/#comment_10706454 وقررت تجربة redux-symbiote .
سمح هذا لإزالة الكيانات غير الضرورية وتقليل مقدار التعليمات البرمجية.

المثال أعلاه بدأ يبدو كالتالي:

 // symbiotes/popups.js import { createSymbiote } from 'redux-symbiote'; export const initState = { opened: [] }; export const { actions, reducer } = createSymbiote(initialState, { popups: { open: { start: state => ({ ...state, error: null }), pending: state => ({ ...state }), success: (state, { name, data } = {}) => ({ ...state, opened: [ ...(state.opened || []).filter(x => x.name !== name), { name, data }) ] }), fail: (state, { error } = {}) => ({ ...state, error }) }, close: { start: state => ({ ...state, error: null }), pending: state => ({ ...state }), success: (state, { name } = {}) => ({ ...state, opened: [ ...state.opened.filter(x => x.name !== name) ] }), fail: (state, { error } = {}) => ({ ...state, error }) } } }); 

 //   import { actions } from './symbiotes/popups'; // ... export default connect( mapStateToProps, dispatch => ({ onClick: () => { dispatch(actions.open.start({ name: PopupNames.Info })); } }) )(FooComponent); 

من الايجابيات لدينا:

  • الكل في ملف واحد
  • رمز أقل
  • تمثيل منظم للإجراءات

من السلبيات:

  • لا تقدم IDE دائمًا تلميحات
  • من الصعب البحث عن عمل في الكود
  • من الصعب إعادة تسمية العمل

على الرغم من السلبيات ، يتم استخدام هذه الوحدة بنجاح في مشاريعنا.

بفضل LestaD للعمل الجيد.

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


All Articles