Redux: рд░реЗрдбреНрдпреВрд╕рд░ рдФрд░ рдХрдВрдкреЛрдиреЗрдВрдЯ рдПрдиреНрд╣рд╛рдВрд╕рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЗрдиреЗрд░рд┐рдХ рд╕реВрдЪреА рдХреИрд╕реЗ рдмрдирд╛рдПрдВ?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 30 рд╕рд┐рддре░ 2015  ┬╖  50рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: reduxjs/redux

рдирдорд╕реНрдХрд╛рд░ред рдХрд╛рдЙрдВрдЯрд░ рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╕реНрд╡рддрдВрддреНрд░ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рдЧрддрд┐рд╢реАрд▓ рд╕реВрдЪреА рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛?

рдбрд╛рдпрдирд╛рдорд┐рдХ рд╕реЗ рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпреВрдЖрдИ рдореЗрдВ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рдЕрдВрдд рдореЗрдВ + рдФрд░ - рдмрдЯрди рд╣реЛрдВрдЧреЗ рдЬреЛ рд╕реВрдЪреА рдореЗрдВ рдПрдХ рдирдпрд╛ рдХрд╛рдЙрдВрдЯрд░ рдЬреЛрдбрд╝рдиреЗ рдпрд╛ рдЕрдВрддрд┐рдо рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реЛрдВрдЧреЗред

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдХрд╛рдЙрдВрдЯрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдФрд░ рдШрдЯрдХ рд╡реИрд╕реЗ рд╣реА рд░рд╣реЗрдВрдЧреЗ рдЬреИрд╕реЗ рд╡реЗ рд╣реИрдВред рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреИрд╕реЗ рдмрдирд╛рдПрдЧрд╛? рдХреНрдпрд╛ рдХрд╛рдЙрдВрдЯрд░ рдФрд░ рдЯреВрдбреВ-рдЖрдЗрдЯрдо рджреЛрдиреЛрдВ рдХреЛ todomvc-example рд╕реЗ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреЛ рдФрд░ рднреА рд╕рд╛рдорд╛рдиреНрдп рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛?

рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдРрд╕рд╛ рдХреБрдЫ рд╣реЛрдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреИрд╕реЗ рдмрдирд╛рдПрдЧрд╛? рдХреНрдпрд╛ рдХрд╛рдЙрдВрдЯрд░ рдФрд░ рдЯреВрдбреВ-рдЖрдЗрдЯрдо рджреЛрдиреЛрдВ рдХреЛ todomvc-example рд╕реЗ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреЛ рдФрд░ рднреА рд╕рд╛рдорд╛рдиреНрдп рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛?

рд╣рд╛рдБ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрднрд╡ рд╣реИред
рдЖрдк рдПрдХ рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдФрд░ рдПрдХ рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рдШрдЯрдХ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ рджреГрд╖реНрдЯрд┐рдХреЛрдг рджреЗрдЦреЗрдВ:

function list(reducer, actionTypes) {
  return function (state = [], action) {
    switch (action.type) {
    case actionTypes.add:
      return [...state, reducer(undefined, action)];
    case actionTypes.remove:
      return [...state.slice(0, action.index), ...state.slice(action.index + 1)];
    default:
      const { index, ...rest } = action;
      if (typeof index !== 'undefined') {
        return state.map(item => reducer(item, rest));
      }
      return state;
    }
  }
}

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return counter + 1;
  case 'DECREMENT':
    return counter - 1;
  }
}

const listOfCounters = list(counter, {
  add: 'ADD_COUNTER',
  remove: 'REMOVE_COUNTER'
});

const store = createStore(listOfCounters);
store.dispatch({
  type: 'ADD_COUNTER'
});
store.dispatch({
  type: 'ADD_COUNTER'
});
store.dispatch({
  type: 'INCREMENT',
  index: 0
});
store.dispatch({
  type: 'INCREMENT',
  index: 1
});
store.dispatch({
  type: 'REMOVE_COUNTER',
  index: 0
});

(рдореИрдВрдиреЗ рдЗрд╕реЗ рдирд╣реАрдВ рдЪрд▓рд╛рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдиреНрдпреВрдирддрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред)

рд╕рднреА 50 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореИрдВ рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИред
рд░реЗрдбрдХреНрд╕ рдпрд╣рд╛рдВ рдПрд▓реНрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡рд╣рд╛рдВ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред

рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреИрд╕реЗ рдмрдирд╛рдПрдЧрд╛? рдХреНрдпрд╛ рдХрд╛рдЙрдВрдЯрд░ рдФрд░ рдЯреВрдбреВ-рдЖрдЗрдЯрдо рджреЛрдиреЛрдВ рдХреЛ todomvc-example рд╕реЗ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реВрдЪреА рд╕реНрдЯреЛрд░ + рдШрдЯрдХ рдХреЛ рдФрд░ рднреА рд╕рд╛рдорд╛рдиреНрдп рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛?

рд╣рд╛рдБ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрднрд╡ рд╣реИред
рдЖрдк рдПрдХ рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдФрд░ рдПрдХ рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рдШрдЯрдХ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ рджреГрд╖реНрдЯрд┐рдХреЛрдг рджреЗрдЦреЗрдВ:

function list(reducer, actionTypes) {
  return function (state = [], action) {
    switch (action.type) {
    case actionTypes.add:
      return [...state, reducer(undefined, action)];
    case actionTypes.remove:
      return [...state.slice(0, action.index), ...state.slice(action.index + 1)];
    default:
      const { index, ...rest } = action;
      if (typeof index !== 'undefined') {
        return state.map(item => reducer(item, rest));
      }
      return state;
    }
  }
}

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return counter + 1;
  case 'DECREMENT':
    return counter - 1;
  }
}

const listOfCounters = list(counter, {
  add: 'ADD_COUNTER',
  remove: 'REMOVE_COUNTER'
});

const store = createStore(listOfCounters);
store.dispatch({
  type: 'ADD_COUNTER'
});
store.dispatch({
  type: 'ADD_COUNTER'
});
store.dispatch({
  type: 'INCREMENT',
  index: 0
});
store.dispatch({
  type: 'INCREMENT',
  index: 1
});
store.dispatch({
  type: 'REMOVE_COUNTER',
  index: 0
});

(рдореИрдВрдиреЗ рдЗрд╕реЗ рдирд╣реАрдВ рдЪрд▓рд╛рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдиреНрдпреВрдирддрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред)

рдзрдиреНрдпрд╡рд╛рдж - рдореИрдВ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред

рдореИрдВ рдЕрднреА рднреА рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪреА рдФрд░ рдЯреВрдбреВ-рдЖрдЗрдЯрдо рдХреА рд╕реВрдЪреА рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП combineReducers рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реВрдЪреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред рдФрд░ рдЕрдЧрд░ рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдЬрд░реВрд░ рдЖрдЬрдорд╛рдКрдВрдЧрд╛ред

рдореИрдВ рдЕрднреА рднреА рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдХрд╛рдЙрдВрдЯрд░ рдХреА рд╕реВрдЪреА рдФрд░ рдЯреВрдбреВ-рдЖрдЗрдЯрдо рдХреА рд╕реВрдЪреА рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдВрдмрд╛рдЗрди рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реВрдЪреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред рдФрд░ рдЕрдЧрд░ рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдЬрд░реВрд░ рдЖрдЬрдорд╛рдКрдВрдЧрд╛ред

рд╣рд╛рдБ, рдмрд┐рд▓рдХреБрд▓:

const reducer = combineReducers({
  counterList: list(counter, {
    add: 'ADD_COUNTER',
    remove: 'REMOVE_COUNTER'
  }),
  todoList: list(counter, {
    add: 'ADD_TODO',
    remove: 'REMOVE_TODO'
  }),
});

@gaearon рд╕реВрдЪреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдЕрдкрдирд╛ index рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП?

рд╣рдо рдЖрдкрдХреЗ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗ рд▓реЗрдХрд┐рди рд╣рдо рдЙрдЪреНрдЪ рдСрд░реНрдбрд░ рдШрдЯрдХ рдХреЗ рд╕рд╛рде рд╕рдВрдШрд░реНрд╖ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдорд╛рд░рд╛ рдШрдЯрдХ рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрдиреНрдп рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╕рд╛рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реИред рд╣рдорд╛рд░рд╛ рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПред

рдЖрдк рд╣рдорд╛рд░рд╛ рд╕рдорд╛рдзрд╛рди рдпрд╣рд╛рдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ: https://github.com/Zeikko/redux/commit/6a222885c8c93950dbdd0d4cf3532cd99a32206c

рдореИрдВрдиреЗ рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд рднрд╛рдЧ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЯрд┐рдкреНрдкрдгреА рдХреЛ рдХрдорд┐рдЯ рдореЗрдВ рдЬреЛрдбрд╝рд╛ред

рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕реВрдЪреА рд░реЗрдбреНрдпреВрд╕рд░ + рдШрдЯрдХ рд╣реЛрдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪрд┐рдпреЛрдВ рдХреА рд╕реВрдЪреА рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдорд╛рд░рд╛ рдШрдЯрдХ рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрдиреНрдп рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╕рд╛рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реИред рд╣рдорд╛рд░рд╛ рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПред

рдХреНрдпрд╛ рдЖрдк рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ "рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ" рд╕реЗ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ? рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЖрдк рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ index рдХреБрдВрдЬреА рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдирд╛рдо рд░рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдЕрдм рддреБрдореНрд╣рд╛рд░рд╛ рдорддрд▓рдм рдорд┐рд▓ рдЧрдпрд╛ рд╣реИред

рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдореИрдВ рдЕрднреА рдЕрдзрд┐рдХ рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдБред рдореИрдВ рдХрд▓ рд╡рд╛рдкрд╕ рдЖрдКрдВрдЧрд╛ред

рдореИрдВ рдЕрдм рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╕рдордЭрддрд╛ рд╣реВрдВред рдЗрд╕рдореЗрдВ рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВред

рд░реЗрдбрдХреНрд╕ рдПрд▓реНрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рд╕реЗ рдХреИрд╕реЗ рд╡рд┐рдЪрд▓рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рдореЗрдВ рдирд┐рд╣рд┐рдд рдХреБрдЫ рд╕реАрдорд╛рдУрдВ рдореЗрдВ рдореИрдВ рдЬрд▓реНрджреА рд╕реЗ рдЯрдХрд░рд╛ рдЧрдпрд╛ред
рдпрд╣ рдЕрдлрд╝рд╕реЛрд╕ рдХреА рдмрд╛рдд рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ рдкрд╣рд▓реЗ рдирд╣реАрдВ рд╕рдордЭрд╛!

  • рдЬрдм рддрдХ рдШрдЯрдХ рд▓рдкреЗрдЯрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрдм рддрдХ рдЙрд╕реЗ dispatch рдкреНрд░реЛрдк рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рди рдХрд┐ рдХреЙрд▓рдмреИрдХред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдпрд╛ рддреЛ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░реНрд╕ рдХреЛ рдЕрдкрдирд╛ рдкреНрд░реЙрдкреНрд╕ рдмрдирд╛рдиреЗ рд╕реЗ рдмрдЪрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХреЗрд╡рд▓ dispatch() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдВрдкреЛрдЬрд╝ рдХрд┐рдП рдЧрдП рдШрдЯрдХреЛрдВ рдореЗрдВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдпрд╛ рд╣рдореЗрдВ рдПрдХ bindActionCreators(Component, actionCreators) => Component рдкреЗрд╢ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдХрд┐ connect() рдЬреИрд╕рд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕реНрдЯреЛрд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдХреЗрд╡рд▓ this.props.dispatch -wanting-component рдХреЗ рд╕рд╛рде action-creator-as-props-wanting-component рдХреА рдЬрдЧрд╣ рд▓реЗрддрд╛ рд╣реИред
  • рдЖрдк рд▓рд┐рдкрдЯреЗ рдШрдЯрдХреЛрдВ рд╕реЗ рдорд┐рдбрд▓рд╡реЗрдпрд░-рдЖрд╡рд╢реНрдпрдХ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдирд╣реАрдВ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рдмрдХрд╡рд╛рд╕ рд╣реИ! рдЕрдЧрд░ рдореИрдВ рдПрдХ рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдЙрдВрдЯрд░ рд▓рдкреЗрдЯрддрд╛ рд╣реВрдВ, рддреЛ рдореИрдВ рдЕрдм incrementAsync() рдкреНрд░реЗрд╖рдг рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдХреНрдпреЛрдВрдХрд┐ function (dispatch, getState) { ... } рдореИрдВрдиреЗ рдЕрднреА-рдЕрднреА рднреЗрдЬрд╛ рд╣реИ рд╕реВрдЪреА рджреНрд╡рд╛рд░рд╛ { action: function (dispatch, getState) { ... } } рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдФрд░ bam! рдердВрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЕрдм рдЗрд╕реЗ рдирд╣реАрдВ рдкрд╣рдЪрд╛рдирддрд╛ рд╣реИред

рдЗрд╕рдХреЗ рдЧреИрд░-рдЕрдЬреАрдм рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдЕрднреА рддрдХ рдирд╣реАрдВ рджреЗрдЦрддрд╛ рд╣реВрдВред
рдЕрднреА рдХреЗ рд▓рд┐рдП, рдХреГрдкрдпрд╛ рдЗрд╕ рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛ рдХреЛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦреЗрдВ (рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╕реАрдорд╛рдУрдВ рдХреЗ рд╕рд╛рде)ред

рдпрд╣рд╛рдБ рдХреЛрдб рд╣реИ:

рдШрдЯрдХ/рдХрд╛рдЙрдВрдЯрд░.рдЬреЗрдПрд╕

import React, { Component, PropTypes } from 'react';
import { increment, incrementIfOdd, incrementAsync, decrement } from '../actions/counter';

class Counter extends Component {
  render() {
    const { dispatch, counter } = this.props;
    return (
      <p>
        Clicked: {counter} times
        {' '}
        <button onClick={() => dispatch(increment())}>+</button>
        {' '}
        <button onClick={() => dispatch(decrement())}>-</button>
        {' '}
        <button onClick={() => dispatch(incrementIfOdd())}>Increment if odd</button>
        {' '}
        <button onClick={() => dispatch(incrementAsync())}>Increment async</button>
      </p>
    );
  }
}

Counter.propTypes = {
  dispatch: PropTypes.func.isRequired,
  counter: PropTypes.number.isRequired
};

export default Counter;

рдШрдЯрдХ/рд╕реВрдЪреА.рдЬреЗрдПрд╕

import React, { Component, PropTypes } from 'react';
import { addToList, removeFromList, performInList } from '../actions/list';

export default function list(mapItemStateToProps) {
  return function (Item) {
    return class List extends Component {
      static propTypes = {
        dispatch: PropTypes.func.isRequired,
        items: PropTypes.array.isRequired
      };

      render() {
        const { dispatch, items } = this.props;
        return (
          <div>
            <button onClick={() =>
              dispatch(addToList())
            }>Add counter</button>

            <br />
            {items.length > 0 &&
              <button onClick={() =>
                dispatch(removeFromList(items.length - 1))
              }>Remove counter</button>
            }
            <br />
            {this.props.items.map((item, index) =>
              <Item {...mapItemStateToProps(item)}
                    key={index}
                    dispatch={action =>
                      dispatch(performInList(index, action))
                    } />
            )}
          </div>
        )
      }
    }
  };
}

рдХрд╛рд░реНрд░рд╡рд╛рдИ/рдХрд╛рдЙрдВрдЯрд░.рдЬреЗрдПрд╕

export const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
export const DECREMENT_COUNTER = 'DECREMENT_COUNTER';

export function increment() {
  return {
    type: INCREMENT_COUNTER
  };
}

export function decrement() {
  return {
    type: DECREMENT_COUNTER
  };
}

export function incrementIfOdd() {
  return (dispatch, getState) => {
    const { counter } = getState();

    if (counter % 2 === 0) {
      return;
    }

    dispatch(increment());
  };
}

export function incrementAsync(delay = 1000) {
  return dispatch => {
    setTimeout(() => {
      dispatch(increment());
    }, delay);
  };
}

рдХреНрд░рд┐рдпрд╛/рд╕реВрдЪреА.рдЬреЗрдПрд╕

export const ADD_TO_LIST = 'ADD_TO_LIST';
export const REMOVE_FROM_LIST = 'REMOVE_FROM_LIST';
export const PERFORM_IN_LIST = 'PERFORM_IN_LIST';

export function addToList() {
  return {
    type: ADD_TO_LIST
  };
}

export function removeFromList(index) {
  return {
    type: REMOVE_FROM_LIST,
    index
  };
}

export function performInList(index, action) {
  return {
    type: PERFORM_IN_LIST,
    index,
    action
  };
}

рд░реЗрдбреНрдпреВрд╕рд░/рдХрд╛рдЙрдВрдЯрд░.рдЬреЗрдПрд╕

import { INCREMENT_COUNTER, DECREMENT_COUNTER } from '../actions/counter';

export default function counter(state = 0, action) {
  switch (action.type) {
  case INCREMENT_COUNTER:
    return state + 1;
  case DECREMENT_COUNTER:
    return state - 1;
  default:
    return state;
  }
}

рд░реЗрдбреНрдпреВрд╕рд░/рд╕реВрдЪреА.рдЬреЗрдПрд╕

import { ADD_TO_LIST, REMOVE_FROM_LIST, PERFORM_IN_LIST } from '../actions/list';

export default function list(reducer) {
  return function (state = [], action) {
    const {
      index,
      action: innerAction
    } = action;

    switch (action.type) {
    case ADD_TO_LIST:
      return [
        ...state,
        reducer(undefined, action)
      ];
    case REMOVE_FROM_LIST:
      return [
        ...state.slice(0, index),
        ...state.slice(index + 1)
      ];
    case PERFORM_IN_LIST:
      return [
        ...state.slice(0, index),
        reducer(state[index], innerAction),
        ...state.slice(index + 1)
      ];
    default:
      return state;
    }
  }
}

рд░реЗрдбреНрдпреВрд╕рд░/index.js

import { combineReducers } from 'redux';
import counter from './counter';
import list from './list'

const counterList = list(counter);

const rootReducer = combineReducers({
  counterList
});

export default rootReducer;

рдХрдВрдЯреЗрдирд░/App.js

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import Counter from '../components/Counter';
import list from '../components/list';

const CounterList = list(function mapItemStateToProps(itemState) {
  return {
    counter: itemState
  };
})(Counter);

export default connect(function mapStateToProps(state) {
  return {
    items: state.counterList
  };
})(CounterList);

cc @acdlite - рдпрд╣рд╛рдБ рд╡рд░реНрддрдорд╛рди рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ + рд░рд┐рдПрдХреНрдЯ рд░реЗрдбрдХреНрд╕ рдбрд┐рдЬрд╝рд╛рдЗрди рдХреБрдЫ рд╣рдж рддрдХ рдЯреВрдЯ рд░рд╣рд╛ рд╣реИред
рд╣рдо рдЗрд╕реЗ рдЕрднреНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рджреЗрдЦрдирд╛ рдЪрд╛рд╣реЗрдВ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рд╣рдо рдЗрд╕реЗ рдЪрдХрдорд╛ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред

рдЪрд╛рд╣реЗрдВрдЧреЗ
https://github.com/erikras/multireducer/ рд╕рд╣рд╛рдпрддрд╛?

рдореИрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗрд╡рд╛ (рдЖрдИрдУрд╕реА) рдХрдВрдЯреЗрдирд░ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдФрд░ рдХрд▓ рдпрд╣ рдкрд░реАрдХреНрд╖рдг-рд░реЗрдкреЛ рдмрдирд╛рдпрд╛: https://github.com/magnusjt/react-ioc

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдХрд╛рдЙрдВрдЯрд░рд▓рд┐рд╕реНрдЯ рдХреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдиреЗ рдмрд┐рдирд╛ рдХрд╛рдЙрдВрдЯрд░ рдкрд░ рдПрдХ рдПрдХреНрд╢рди рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рд▓рд┐рдП рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИ, рдкреНрд░реЙрдкрд░ рдореЗрдВ рдирд╣реАрдВред

рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЧрдП рдкреНрд░рддреНрдпреЗрдХ рдирдП рдХрд╛рдЙрдВрдЯрд░ рдШрдЯрдХ рдХреЗ рд▓рд┐рдП, рдЖрдк рдПрдХ рдЕрд▓рдЧ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╢рд╛рдпрдж рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рд╡реИрд▓реНрдпреВ рдХреЛ рдмрд╛рдЗрдВрдб рдХрд░рдХреЗ)ред рдмреЗрд╢рдХ рдЖрдкрдХреЛ рдЕрднреА рднреА рдХрд╛рдЙрдВрдЯрд░ рдкрд░ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдореБрдЭреЗ рдЕрднреА рддрдХ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдРрд╕рд╛ рдХреБрдЫ рд╣реИ рдЬрд┐рд╕реЗ рд╕рд░реНрд╡рд┐рд╕ рдХрдВрдЯреЗрдирд░ рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

@gaearon , рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рдореЗрд░реЗ рд▓рд┐рдП рд╕рд╣реА рджрд┐рдЦрддрд╛ рд╣реИред рдЖрдкрдХреЛ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░реНрд╕ рдХреЛ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рд╕рднреА рддрд░рд╣ рд╕реЗ рдиреАрдЪреЗ рднреЗрдЬрдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕ рддрд░рд╣ рдЖрдк рдЙрдЪреНрдЪ-рдХреНрд░рдо рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рджреВрд╕рд░рд╛ рдмрд┐рдВрджреБ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдирдП рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рд░реВрдк рдХреЗ рдХрд╛рд░рдг рдЖрдк рдорд┐рдбрд▓рд╡реЗрдпрд░ рд╕реЗ рдЪреВрдХ рдЬрд╛рдПрдВрдЧреЗ, рд▓реЗрдХрд┐рди performInList рдХреЗ рд╕рд╛рде рдПрдХ рдмрдбрд╝реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдЕрдореВрд░реНрддрддрд╛ рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рд╕реВрдЪреА рддрдХ рд╕реАрдорд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИред @ pe3 рдиреЗ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪрд┐рдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ред рдЗрд╕ рддрд░рд╣ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рдХреА рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдШреЛрдВрд╕рд▓рд╛ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ред

рдЗрд╕ рдЯрд┐рдХрдЯ рдореЗрдВ, рдореИрдВ рдШреЛрдВрд╕рд▓реЗ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рддрд░реАрдХрд╛ рд▓реЗрдХрд░ рдЖрдпрд╛ рд╣реВрдВ:
https://github.com/rackt/redux/issues/897

рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдзрд┐рдХ рдореМрд▓рд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдШреЛрдВрд╕рд▓рд╛ рдмрдирд╛рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ ....

рдареАрдХ рд╣реИ, рдореИрдВрдиреЗ рдЕрднреА рдЗрд╕реЗ рдЬрд╛рдирд╛ рдерд╛ред

рдореИрдВрдиреЗ рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рдлреА рд╕рд░рд▓ рдХрд┐рдпрд╛ред рдЗрд╕ рдлреИрдВрд╕реА рд╕рд╛рдорд╛рди рдХреЛ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣рд╛рдВ рдХрд╛рдЙрдВрдЯрд░ рдРрдк рд╣реИ:

https://github.com/ccorcos/redux-lifted-reducers/blob/80295a09c4d04654e6b36ecc8bc1bfac4ae821c7/index.js#L49

рдФрд░ рдпрд╣рд╛рдБ рдЗрд╕рдХреЗ рдмрд╛рдж рд╣реИ:

https://github.com/ccorcos/redux-lifted-reducers/blob/1fdafe8ed29303822018cde4973fda3305b43bb6/index.js#L57

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ "рд▓рд┐рдлреНрдЯ" рдЙрдЪрд┐рдд рд╢рдмреНрдж рд╣реИ - рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдореЗрдВ рдХреБрдЫ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдареАрдХ рд▓рдЧрд╛ред

рдореВрд▓ рд░реВрдк рд╕реЗ, рдПрдХ рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЙрдард╛рдХрд░, рдЖрдк рдПрдХ рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреВрд╕рд░реЗ рдХреЗ рднреАрддрд░ рдШреЛрдВрд╕рд▓рд╛ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред

const liftActionCreator = liftingAction => actionCreator => action => Object.assign({}, liftingAction, { nextAction: actionCreator(action) })

рдФрд░ рдиреЗрд╕реНрдЯреЗрдб рдХреНрд░рд┐рдпрд╛ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЛ рдЙрдард╛рдХрд░ рджреВрд░ рд╣реЛ рдЬрд╛рддреА рд╣реИред рд▓рд┐рдлреНрдЯрд┐рдВрдЧ рд░рд┐рдбреНрдпреВрд╕рд░ рдореВрд▓ рд░реВрдк рд╕реЗ рд╕рдм-рд░реЗрдбреНрдпреВрд╕рд░ (рдЬреЛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреБрдХреНрдд рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ) рдХреЛ рдХреБрдЫ рд╕рдмрд╕реНрдЯреЗрдЯ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

const liftReducer = liftingReducer => reducer => (state, action) => liftingReducer(state, action)((subState) => reducer(subState, action.nextAction))

рддреЛ рдШрдЯрдХ рд░реЗрдбреНрдпреВрд╕рд░ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП, рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдХреНрд░рд┐рдпрд╛ рд╣реИ рдЬреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреА рд╣реИ рдХрд┐ рдЙрдк-рдХреНрд░рд┐рдпрд╛ рдХрд┐рд╕ рдШрдЯрдХ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИред

// list actions
const LIST_INDEX = 'LIST_INDEX'
function actOnIndex(i) {
  return {
    type: LIST_INDEX,
    index: i
  }
}

рдФрд░ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ "рд╣рд╛рдИ-рдСрд░реНрдбрд░" (рдПрдХ рдФрд░ рдлреИрдВрд╕реА рд╢рдмреНрдж рд╣реИ рдЬреЛ рдЕрднреА рд╕рд╣реА рд▓рдЧрд╛, рд╣рд╛рд╣рд╛;) рд░реЗрдбреНрдпреВрд╕рд░ рдЬреЛ рдЙрдк-рд░реЗрдбреНрдпреВрд╕рд░ рдХреЛ рдЙрдкрдпреБрдХреНрдд рдЙрдк-рд░рд╛рдЬреНрдп рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

const list = (state=[], action) => (reduce) => {
  switch (action.type) {
    case LIST_INDEX:
      let nextState = state.slice(0)
      nextState[action.index] = reduce(nextState[action.index])
      return nextState
    default:
      return state;
  }
}

рдФрд░ рдЬреЛ рдХреБрдЫ рдмрдЪрд╛ рд╣реИ рд╡рд╣ рд╕реВрдЪреА рд░реЗрдбреНрдпреВрд╕рд░ рдореЗрдВ рдЧрд┐рдирддреА рд░реЗрдбреНрдпреВрд╕рд░ рдХреЛ "рдЙрдард╛рдирд╛" рд╣реИред

const reducer = combineReducers({
  counts: liftReducer(list)(count)
});

рдФрд░ рдЕрдм рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЙрдард╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрд╛рддреЗ рд╣реИрдВред

class App extends Component {
  render() {
    const counters = [0,1,2,3,4].map((i) => {
      return (
        <Counter count={this.props.state.counts[i]}
                 increment={liftActionCreator(actOnIndex(i))(increment)}
                 decrement={liftActionCreator(actOnIndex(i))(decrement)}
                 dispatch={this.props.dispatch}
                 key={i}/>
      )
    })
    return (
      <div>
        {counters}
      </div>
    );
  }
}

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЙрдЪрд┐рдд рд▓рд┐рдВрдЧреЛ рдХреЗ рд╕рд╛рде рдФрд░ рдЕрдзрд┐рдХ рдФрдкрдЪрд╛рд░рд┐рдХ рд░реВрдк рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЙрдЪреНрдЪ-рдХреНрд░рдо рд╡рд╛рд▓реЗ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рднреА рдпрд╣рд╛рдВ рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдХрднреА рднреА рдЙрдирдХрд╛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд╣рд╛рд╣рд╛ред

рдФрд░ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реА рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ рдЬреЛ рдХрд╣рд╛ рдерд╛, рдореИрдВ рдЙрд╕реЗ рд╡рд╛рдкрд╕ рд▓реЗрддрд╛ рд╣реВрдВ - @gaearon рд╕рд╣реА рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдиреЗрд╕реНрдЯ рдХрд░рдХреЗ, рдЖрдк рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рдпрд╛рдж рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдЖрдкрдХреЛ рд╕рднреА рддрд░рд╣ рд╕реЗ рдбрд┐рд╕реНрдкреИрдЪ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рддрд╛рдХрд┐ рдЖрдк рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░реНрд╕ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░ рд╕рдХреЗрдВред рд╢рд╛рдпрдж рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Redux рдХреЛ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдЙрдк-рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕рд╛рде рд╣реА, рдПрдХ рдФрд░ рдореБрджреНрджрд╛ рд░рд╛рдЬреНрдп рдХреЛ рд╕реВрдЪреА рдореЗрдВ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реИ ...

рдЖрдк рдЬреЛ рд╡рд░реНрдгрди рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЙрд╕реЗ рдПрд▓реНрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ: https://github.com/gaearon/react-elmish-example

рдпрд╛рд░, рддреБрдо рд╣рдореЗрд╢рд╛ рдПрдХ рдХрджрдо рдЖрдЧреЗ рд╣реЛ! рдореБрдЭреЗ рд╢рд╛рдВрдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рд╕реНрдирд╛рди рдХрд░реЗрдВ: +1:

рдЖрдк рд▓рд┐рдкрдЯреЗ рдШрдЯрдХреЛрдВ рд╕реЗ рдорд┐рдбрд▓рд╡реЗрдпрд░-рдЖрд╡рд╢реНрдпрдХ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдирд╣реАрдВ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рдмрдХрд╡рд╛рд╕ рд╣реИ! рдпрджрд┐ рдореИрдВ рдПрдХ рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдЙрдВрдЯрд░ рд▓рдкреЗрдЯрддрд╛ рд╣реВрдВ, рддреЛ рдореИрдВ рдЕрдм рд╡реЗрддрди рд╡реГрджреНрдзрд┐ рдирд╣реАрдВ рднреЗрдЬ рд╕рдХрддрд╛ () рдХреНрдпреЛрдВрдХрд┐ рдлрд╝рдВрдХреНрд╢рди (рдкреНрд░реЗрд╖рдг, рдЧреЗрдЯрд╕реНрдЯреЗрдЯ) {...} рдореИрдВрдиреЗ рдЕрднреА-рдЕрднреА рднреЗрдЬрд╛ рд╣реИ {рдХреНрд░рд┐рдпрд╛: рдлрд╝рдВрдХреНрд╢рди (рдкреНрд░реЗрд╖рдг, рдЧреЗрдЯрд╕реНрдЯреЗрдЯ) {...}} рджреНрд╡рд╛рд░рд╛ рд╕реВрдЪреА- рдФрд░ рдмреЗрдо! рдердВрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЕрдм рдЗрд╕реЗ рдирд╣реАрдВ рдкрд╣рдЪрд╛рдирддрд╛ рд╣реИред

@gaearon рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ? рдЬреЗрдиреЗрд░рд┐рдХ рд░рд┐рдбреНрдпреВрд╕рд░ рдХреЗ рдмрдЬрд╛рдп рдЦреБрдж рдХреЛ рдЪрд╛рдЗрд▓реНрдб рд░рд┐рдбреНрдпреВрд╕рд░ рдЗрд╕ рддрд░рд╣ рдХрд╣рддреЗ рд╣реИрдВ

case PERFORM_IN_LIST:
      return [
        ...state.slice(0, index),
        reducer(state[index], innerAction),
        ...state.slice(index + 1)
      ];

рд╕реНрдЯреЛрд░ рдХреЛ рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рдзрд┐ dispatchTo(reducer, state, action, callback) рдХреЗ рд╕рд╛рде рдкреНрд░рджрд╛рди рдХрд░реЗрдВ рдЬреЛ dispatch рдХреА рддрд░рд╣ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдпрд╣ рд╕реАрдзреЗ рдПрдХ рдмрдЪреНрдЪреЗ рд░реЗрдбреНрдпреВрд╕рд░ (рд╕рднреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдХреЛ рдкреНрд░реЗрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдмрдЪреНрдЪреЗ рдХреЗ рд░рд╛рдЬреНрдп рд╕рдВрд╢реЛрдзрди рдкрд░ рдХреЙрд▓рдмреИрдХ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ

export default function list(reducer, dispatchTo) {
  return function (state = [], action) {
    ...
    case PERFORM_IN_LIST:
      dispatchTo(reducer, state[index], innerAction, newState =>
         [
           ...state.slice(0, index),
           newState,
           ...state.slice(index + 1)
        ]);
       default:
          return state;
    }
  }
}

рдореБрдЭреЗ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ Redux рдореЗрдВ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдпрд╛ рдирд╣реАрдВред рдПрдХ рд╡рд┐рдЪрд╛рд░ dispatchTo рдХреЛ рдХреБрдЫ рдЖрдВрддрд░рд┐рдХ store.derive(reducer, state) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд░реВрдЯ рд╕реНрдЯреЛрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХреБрдЫ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рд░рд╛рдЬреНрдп рдкреЗрдбрд╝ рдХреЗ рдЙрд╕ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд▓ рд╕реНрдЯреЛрд░ рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

function dispatchTo(reducer, state, action, callback) {
  const childStore = store.derive(reducer, state)
  childStore.subscribe(() => setRootState( callback(getState() ))
  childStore.dispatch(action)
}

рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛ рдерд╛ рдХрд┐ рдореБрдЭреЗ Redux рдХреЗ рдЗрдВрдЯрд░реНрдирд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдЗрд╕рд▓рд┐рдП рд╢рд╛рдпрдж рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рдЖрдпрд╛

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ
_рд╢рд╛рдпрдж рдпрд╣ рдЕрдЬреАрдм рд╣реЛрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рд░реЗрдбреНрдпреВрд╕рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рд╡рд┐рдзрд┐ рдмрдирд╛рдиреЗ рд╕реЗ async рдХрд╛ рддрд╛рддреНрдкрд░реНрдп рд╣реИ рдХрд┐ рд╕рднреА рд╢реНрд░реГрдВрдЦрд▓рд╛рдУрдВ рдХреЛ рднреА async рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рд╕реАрдзреЗ store.derive(reducer) рд╡рд┐рдзрд┐ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдирд╛ рдФрд░ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рд╕реНрдЯреЛрд░ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рд░реЗрдбреНрдпреВрд╕рд░ рдмрдирд╛рдирд╛ рд╣реИред

рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓рддрд╛ рд╣реИ рдФрд░ рдЖрдИрдПрдордУ рдХреЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдмрд╕ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ (рдпрд╛ applyMiddleware рдХреЗ рдХреБрдЫ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ) рдФрд░ рдЖрдк рдкреВрд░реА рддрд░рд╣ рддреИрдпрд╛рд░ рд╣реИрдВред

рд╕рд╛рде рд╣реА, рдореИрдВ рдмрдВрдж рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реА рдЗрд╕ рдкрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рд╣реИред

@gaearon рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП:
рдЗрд╕ рдХрдорд┐рдЯ рдореЗрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд▓рдЧреНрди рдХреЛрдб рдЙрджрд╛рд╣рд░рдг: https://github.com/rackt/redux/commit/a83002aed8e36f901ebb5f139dd14ce9c2e4cab4

рдпрджрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА 2 рд╕реВрдЪрд┐рдпрд╛рдВ рд╣реИрдВ (рдпрд╛ рдЕрд▓рдЧ 'рдореЙрдбрд▓' рднреА), рддреЛ addToList рдкреНрд░реЗрд╖рдг рджреЛрдиреЛрдВ рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рджреЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░ рд╕рдорд╛рди рд╣реИрдВред

// reducers/index.js

import { combineReducers } from 'redux';
import counter from './counter';
import list from './list'

const counterList = list(counter);
const counterList2 = list(counter);

const rootReducer = combineReducers({
  counterList,
  counterList2
});

export default rootReducer;

рддреЛ reducers/list рдпрд╣рд╛рдБ рдХреИрд╕реЗ рдорджрдж рдХрд░рддрд╛ рд╣реИ? рдХреНрдпрд╛ рдЖрдкрдХреЛ рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХреБрдЫ рдЙрдкрд╕рд░реНрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ?

рдпрджрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА 2 рд╕реВрдЪрд┐рдпрд╛рдВ рд╣реИрдВ (рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рдЕрд▓рдЧ 'рдореЙрдбрд▓'), рддреЛ addToList рдкреНрд░реЗрд╖рдг рджреЛрдиреЛрдВ рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рджреЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░ рд╕рдорд╛рди рд╣реИрдВред

рдХреГрдкрдпрд╛ a83002aed8e36f901ebb5f139dd14ce9c2e4cab4 рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдпрд╣ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдШреЛрдВрд╕рд▓рд╛ рдмрдирд╛рддрд╛ рд╣реИред dispatch рдЬреЛ рдХрдВрдЯреЗрдирд░ рдШрдЯрдХ рд╕реЗ рдиреАрдЪреЗ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ performInList рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдлрд┐рд░ рд░реЗрдбреНрдпреВрд╕рд░ рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рдлреА рд╣рдж рддрдХ рдПрд▓реНрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

@gaearon рд╢рд╛рдпрдж рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдКрдкрд░ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдЕрддрд┐рд░рд┐рдХреНрдд counterList2 рд░рд┐рдбреНрдпреВрд╕рд░ рдХреЗ рд╕рд╛рде, рдпрд╣ UI рдЕрднреА рднреА рдкреНрд░рддреНрдпреЗрдХ рдХреНрд░рд┐рдпрд╛ рдкрд░ рджреЛрдиреЛрдВ рд╕реВрдЪрд┐рдпреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ (рдЬреЛ рдХрд┐ рдЗрд╕рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИ?):

// reducers/index.js

import { combineReducers } from 'redux';
import counter from './counter';
import list from './list'

const counterList = list(counter);
const counterList2 = list(counter);

const rootReducer = combineReducers({
  counterList,
  counterList2
});

export default rootReducer;


// containers/App.js

import React from 'react';

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import counter from '../components/Counter';
import list from '../components/list';

let CounterList = list(function mapItemStateToProps(itemState) {
  return {
    counter: itemState
  };
})(counter);

CounterList = connect(function mapStateToProps(state) {
  return {
    items: state.counterList
  };
})(CounterList);

let CounterList2 = list(function mapItemStateToProps(itemState) {
  return {
    counter: itemState
  };
})(counter);

CounterList2 = connect(function mapStateToProps(state) {
  return {
    items: state.counterList2
  };
})(CounterList2);


export default class App extends React.Component {
  render() {
    return (
      <div>
        <CounterList />
        <CounterList2 />
      </div>
    )
  }
}

@elado рдЖрдкрдХреЛ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдПрдХ рд╕реВрдЪреА рдореЗрдВ рд▓рдкреЗрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рддрд╛рдХрд┐ рдХреНрд░рд┐рдпрд╛рдПрдВ рджреЛ рд╕реВрдЪрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрдШрд░реНрд╖ рди рдХрд░реЗрдВ, рдареАрдХ рдЙрд╕реА рддрд░рд╣ рдЬреИрд╕реЗ рд╣рдордиреЗ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдерд╛

@ccorcos

рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд╕реВрдЪреА рдореЗрдВ рд▓рдкреЗрдЯрдиреЗ рдХреЗ рд▓рд┐рдП

рдХреНрдпрд╛ рд▓рдкреЗрдЯреЛ?

@ccorcos
рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рдЙрджрд╛рд╣рд░рдг рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рд╣реИ: http://elado.s3-website-us-west-1.amazonaws.com/redux-counter/
рдЗрд╕рдореЗрдВ рд╕реНрд░реЛрдд рдорд╛рдирдЪрд┐рддреНрд░ рд╣реИрдВ

рдЕрднреА рднреА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рдерд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛ - рд╡рд░реНрддрдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рдирд╛рдо рд╕рдорд╛рди рд╣реИрдВ, рдФрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рдХреЛрдИ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХрд┐рд╕ рд╕реВрдЪреА рдореЗрдВ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕рднреА рд░реЗрдбреНрдпреВрд╕рд░ рдкрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЪрд▓рд╛рддрд╛ рд╣реИ рдЬреЛ рдЕрдВрддрддрдГ рджреЛрдиреЛрдВ рд╕реВрдЪрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ Redux рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдЬрд╛рдирддрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдПрд▓реНрдо рд╕реЗ рдмрд╣реБрдд рдкрд░рд┐рдЪрд┐рдд рд╣реВрдВред

рдЗрд╕ рдирдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░реНрд╕ рдХреЛ рд╢реАрд░реНрд╖ рд╕реНрддрд░ рдкрд░ рдмрд╛рдзреНрдп рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдбрд┐рд╕реНрдкреИрдЪ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рдЪрд▓реЗ рдШрдЯрдХреЛрдВ рдореЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡реЗ рдирд┐рдЪрд▓реЗ рдШрдЯрдХ рдбрд┐рд╕реНрдкреИрдЪ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдПрдХ рдХреНрд░рд┐рдпрд╛ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдПрдмреНрд╕реНрдЯреНрд░реИрдХреНрд╢рди рдХреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд╛рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХреНрд╢рди рдЯрдХрд░рд╛рд╡ рди рд╣реЛ, рдЬрдм "рд▓рд┐рд╕реНрдЯрдСрдл" рдШрдЯрдХ рдЕрдкрдиреЗ рдмрдЪреНрдЪреЛрдВ рдХреЛ рдкреНрд░реЗрд╖рдг рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдХреНрд░рд┐рдпрд╛ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╕реВрдЪреА рдШрдЯрдХ рд╕рдордЭ рд╕рдХрддрд╛ рд╣реИред

children.map((child, i) => {
  childDispatch = (action) => dispatch({action, index: i})
  // ...

рддреЛ рдЕрдм рдЖрдк listOf(counter) рдпрд╛ listOf(listOf(counter)) рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдЖрдк pairOf рдирд╛рдордХ рдПрдХ рдШрдЯрдХ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЬрдм рдЖрдк рдЙрдиреНрд╣реЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЖрдкрдХреЛ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд▓рдкреЗрдЯрдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЕрднреА, App рдШрдЯрдХ рдХреЗрд╡рд▓ рдкреНрд░реЗрд╖рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рдкреЗрдЯреЗ рдмрд┐рдирд╛ рдЙрдиреНрд╣реЗрдВ рдХрдВрдзреЗ рд╕реЗ рдХрдВрдзрд╛ рдорд┐рд▓рд╛рдХрд░ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЯрдХрд░рд╛рд╡ рд╣реИред

@ccorcos

рдзрдиреНрдпрд╡рд╛рджред рддреЛ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХреЛрдИ "рдЬрд╛рджреВ" рдирд╣реАрдВ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдЙрди рд╕рднреА рд╕реВрдЪрдирд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдЙрдиреНрд╣реЗрдВ рд░рд┐рдбреНрдпреВрд╕рд░ рдХреЛ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддреА рд╣реИрдВ рдХрд┐ рдХрд┐рд╕ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рдиреА рд╣реИред рдпрджрд┐ рдпрд╣ listOf(listOf(counter)) рд╣реИ рддреЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП 2d рд╕рд░рдгреА рдХреЗ рджреЛрдиреЛрдВ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред listOf(listOf(counter)) рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╕рднреА рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреЛ рдПрдХ рд╣реА рдлреНрд▓реИрдЯ рд╕реВрдЪреА рдореЗрдВ рдЕрджреНрд╡рд┐рддреАрдп рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдХрд┐ рдПрдХ рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкрд╛рд░рд┐рдд рдПрдХрдорд╛рддреНрд░ рдЪреАрдЬ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реА рд▓рдЧрддреА рд╣реИред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рд▓рдЪреАрд▓рд╛ рдФрд░ рдЬрдЯрд┐рд▓ Redux рдРрдк рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╕реНрдЯреЛрд░ рдореЗрдВ рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдорд┐рдд рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕рднреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХрд╛ рд╣реЛрдирд╛ рд╣реИред рдХреЛрдИ рдЕрдиреНрдп рд╕рд░рд▓ рджреГрд╖реНрдЯрд┐рдХреЛрдг, рдЬреЛ рдХрднреА-рдХрднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЗрдЬреА рд╕реЗ рдЕрдкрдиреА рд╕реАрдорд╛ рддрдХ рдкрд╣реБрдВрдЪ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рд╕реВрдЪрдХрд╛рдВрдХ рд▓рдЧрднрдЧ рдПрдХ рд╕рдВрдмрдВрдзрдкрд░рдХ рдбреАрдмреА рдХрд╛ рджрд░реНрдкрдг рд╣реИред

рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП 2d рд╕рд░рдгреА рдХреЗ рджреЛрдиреЛрдВ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдЖрдк рд╕реЛрдЪ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:

{type: 'increment', index:[0 5]}

рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдРрд╕рд╛ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

{type:'child', index: 0, action: {type: 'child', index: 5, action: {type: 'increment'}}}

рдЗрд╕ рддрд░рд╣ рдЖрдк listOf(listOf(listOf(...listOf(counter)...))) рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!

рдпрд╣ рд╕рдм рдПрд▓реНрдо рд╕реЗ рдЖрддрд╛ рд╣реИ, рдмреАрдЯреАрдбрдмреНрд▓реНрдпреВред рдПрд▓реНрдо рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рджреЗрдЦреЗрдВ

рдореИрдВ рдкрд╛рд░реНрдЯреА рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдзреАрдорд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдпрд╣ "рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛" рдХрд╣рд╛рдВ рд╣реИ? рдпрджрд┐ рдЖрдк @ccorcos рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдирдВрдд рдШреЛрдВрд╕рд▓реЗ рдХреА рдкреЗрд╢рдХрд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдХреНрдпрд╛ рдЖрдк рдШреЛрдВрд╕рд▓реЗ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рддрд╛рд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ? рдпрд╛ рд╣рдо рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ redux-thunk рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдиреЗрд╕реНрдЯреЗрдб рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдЕрд░реНрде рдЕрдЬреАрдмрддрд╛ рд╣реЛрдЧрд╛?

рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рдХреИрд╕реЗ рдкрддрд╛ рдЪрд▓реЗрдЧрд╛ рдХрд┐ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ рдпрд╛ рдиреЗрд╕реНрдЯреЗрдб рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рдирд╛ рд╣реИ?

рдЖрд╣ред

@gaearon

рдирдорд╕реНрддреЗред

рдореИрдВ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдирд╣реАрдВ рд╣реВрдВ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рд╕рдВрдХрд▓реНрдк рдХреЛ рд╕рдордЭрддрд╛ рд╣реВрдВ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕рд░рд▓ рдЙрддреНрддрд░ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддрд╛ рд╣реВрдВред

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╣реА рдкреГрд╖реНрда рдкрд░ рдШрдЯрдХ рдХреА рдПрдХрд╛рдзрд┐рдХ рдкреНрд░рддрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ рдХреНрдпрд╛ рдпрд╣ рдорд┐рдбрд▓рд╡реЗрдпрд░ (рдФрд░ рдореВрд▓ рд░реВрдк рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ Redux рдкрд╛рд░рд┐рд╕реНрдерд┐рддрд┐рдХреА рддрдВрддреНрд░) рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ? рдореИрдВрдиреЗ рдпрд╣ рднреА рдирд╣реАрдВ рджреЗрдЦрд╛ рдХрд┐ рдХрд┐рд╕реА рдиреЗ рдорд▓реНрдЯреАрд░реЗрдбреНрдпреВрд╕рд░ рд╕реБрдЭрд╛рд╡ рдХрд╛ рдЬрд╡рд╛рдм рджрд┐рдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдХреЛрдИ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдорджрдж рдХрд░реЗрдЧрд╛ред

рдирд╣реАрдВ, рдпрд╣ рд╕рдВрдХрд▓реНрдк рдирд╣реАрдВ рд╣реИред рдереНрд░реЗрдб рдкреГрд╖реНрда рдкрд░ рдХрд┐рд╕реА рдШрдЯрдХ рдХреА рдПрдХрд╛рдзрд┐рдХ рдкрд╣рдЪрд╛рди рд░рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЖрдИрдбреА рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрд╛рдЧрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдерд╛_ред рдЬреЛ рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рд╕реЗ рдЯрдХрд░рд╛рддрд╛ рд╣реИред

рд╢реБрдХреНрд░рд┐рдпрд╛ред

рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░,
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░ рджрд┐рдпрд╛ рд╣реЛ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ deku рд╕реЗ рдЕрдзрд┐рдХ react ^^ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ

рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреА рдЕрдЧрд░ рдХреЛрдИ рдореБрдЭреЗ рдЗрд╕ рдкреНрд░рдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдкрдиреА рдЕрдВрддрд░реНрджреГрд╖реНрдЯрд┐ рджреЗрдЧрд╛, рдЦрд╛рд╕рдХрд░ taskMiddleware рд╡рд┐рдЪрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред @gaearon рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рдордп рд╣реИ? :рдЬреБрдмрд╛рди:

рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рд╕реВрдЪреА

рдзрдиреНрдпрд╡рд╛рдж!

рдмрд╕ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рд╕рдорд╛рдзрд╛рди рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХрд╛ рд▓рдХреНрд╖реНрдп рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИред
рдХреНрдпрд╛ рдпрд╣ рдХрд┐рд╕реА рддрд░рд╣ @gaearon рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реВрдЪреА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрд░реЛрдХреНрдд рд╕реВрдЪреА рд░реЗрдбреНрдпреВрд╕рд░ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛?

рдпрд╣ рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд рдХреНрдпреЛрдВ рд╣реЛрдЧрд╛? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЪрд╛рдЗрд▓реНрдб рд░рд┐рдбреНрдпреВрд╕рд░ рдХреЛ undefined рд░рд╛рдЬреНрдп рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрди рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЬрдм рд╕реНрдЯреЛрд░ рдХреЛ рдкрд╣рд▓реЗ рдкреНрд░реЗрд╖рдг рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдореБрдЭреЗ рдЙрд╕ рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП (рдореЗрд░реЗ рдЖрдВрддрд░рд┐рдХ рддрд░реНрдХ рдХреЗ рд▓рд┐рдП) рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдпрд╣ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╕реВрдЪреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП (рд╕реВрдЪреА рдХреЗ рдЖрдЗрдЯрдо рдХрд╛ рдкреНрд░рдХрд╛рд░)

рдХреБрдЫ рдЗрд╕ рддрд░рд╣?

export default function list(reducer) {
  return function (state = [

    // e.g. 2 counters with default values
    reducer(undefined, {}),
    reducer(undefined, {}),

      ], action) {
    const {
      index,
      action: innerAction
    } = action;
   // ...
  }
}

рдпрджрд┐ рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдЖрдк рдЗрд╕реЗ list рдХреЗ рд▓рд┐рдП рднреА рддрд░реНрдХ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ

рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЬрдЯрд┐рд▓ рд▓рдЧрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдкреГрд╖реНрда рдкрд░ рдПрдХ рд╣реА рдШрдЯрдХ рдХреЗ рдПрдХрд╛рдзрд┐рдХ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

рдореИрдВ рдЕрднреА рднреА Redux рдХреЗ рдЖрд╕рдкрд╛рд╕ рдЕрдкрдирд╛ рд╕рд┐рд░ рд▓рдкреЗрдЯ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдХрдИ рд╕реНрдЯреЛрд░ рдмрдирд╛рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд▓рдЧрддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдпрд╣ рдЕрдиреБрд╢рдВрд╕рд┐рдд Redux рдЙрдкрдпреЛрдЧ рдкреИрдЯрд░реНрди рди рд╣реЛред

@deevus : рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдЪрд░реНрдЪрд╛рдУрдВ рдХреЛ рдЖрдкрдХреЛ рдбрд░рд╛рдиреЗ рди рджреЗрдВред Redux рд╕рдореБрджрд╛рдп рдореЗрдВ рдмрд╣реБрдд рд╕реЗ рд▓реЛрдЧ рд╣реИрдВ рдЬреЛ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреА рдУрд░ рдмрд╣реБрдд рдЙрдиреНрдореБрдЦ рд╣реИрдВ, рдФрд░ рдЬрдмрдХрд┐ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рдХреБрдЫ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдФрд░ рдЗрд╕реА рддрд░рд╣ рдХреЗ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХрд╛ рдореВрд▓реНрдп рд╣реИ, рд╡реЗ рднреА "рдкрд░рд┐рдкреВрд░реНрдг" рдХреЗ рд▓рд┐рдП рдЬрд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред , рдХреЗрд╡рд▓ "рдЕрдЪреНрдЫреЗ" рдХреЗ рдмрдЬрд╛рдпред

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдкреГрд╖реНрда рдкрд░ рдПрдХ рдШрдЯрдХ рдХреЗ рдХрдИ рдЙрджрд╛рд╣рд░рдг рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдЪрд░реНрдЪрд╛ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдиреЗрд╕реНрдЯреЗрдб рдШрдЯрдХреЛрдВ рдХреА рдордирдорд╛рдиреА рд░рдЪрдирд╛ рд╣реИ, рдЬреЛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдРрдкреНрд╕ рдХреЛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЗрд╕рд╕реЗ рдкрд░реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЪрд┐рдВрддрд╛рдПрдВ рд╣реИрдВ, рддреЛ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлрд╝реНрд▓реЛ рдЖрдорддреМрд░ рдкрд░ рдкреНрд░рд╢реНрди рдкреВрдЫрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫреА рдЬрдЧрд╣ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбрд┐рд╕реНрдХреЙрд░реНрдб рдкрд░ рд░рд┐рдПрдХреНрдЯрд┐рдлреНрд▓рдХреНрд╕ рд╕рдореБрджрд╛рдп рдХреЗ рдкрд╛рд╕ рдЪреИрдЯ рдЪреИрдирд▓реЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд╣реИ рдЬреЛ рд░рд┐рдПрдХреНрдЯ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рддрдХрдиреАрдХреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИ, рдФрд░ рд╣рдореЗрд╢рд╛ рдХреБрдЫ рд▓реЛрдЧ рдмрд╛рдд рдХрд░рдиреЗ рдФрд░ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд░рд╣рддреЗ рд╣реИрдВред

@markerikson рдзрдиреНрдпрд╡рд╛рджред рдореИрдВ рдбрд┐рд╕реЙрд░реНрдбрд░ рдкрд░ рд░рд┐рдПрдХреНрдЯрд┐рдлреНрд▓рдХреНрд╕ рд╕реЗ рдХреБрдЫ рдорджрдж рд▓реЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред

рдЗрд╕ рдкрд░ рдЕрдиреБрд╡рд░реНрддреА:
рдореБрдЭреЗ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд░реЗрдбреНрдпреВрд╕рд░ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕реНрдХреЗрд▓реЗрдмрд▓ рддрд░реАрдХрд╛ рдорд┐рд▓рд╛, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рднреАрддрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рднреА рдХрд┐рдпрд╛ред

рдиреЗрдорд╕реНрдкреЗрд╕ рдкреНрд░рддрд┐рдорд╛рди

рдпрд╣ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИ рдХрд┐ рдХрдИ "рдЖрдВрд╢рд┐рдХ" рд░реЗрдбреНрдпреВрд╕рд░ рдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ "рдиреЗрдорд╕реНрдкреЗрд╕" рд╕рдВрдкрддреНрддрд┐ рд╣реЛрддреА рд╣реИ рдЬреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреА рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рд░реЗрдбреНрдпреВрд╕рд░ _all_ рдХреЗ рд╡рд┐рдкрд░реАрдд рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╕рдВрднрд╛рд▓реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдПрдХ рд╣реА рдХреНрд░рд┐рдпрд╛ type рд╕реБрдирддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг https://github.com/reactjs/redux/issues/822#issuecomment-172958967 рдореЗрдВ

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬрд┐рди рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдирд╛рдорд╕реНрдерд╛рди рдирд╣реАрдВ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдЕрднреА рднреА рдЕрдиреНрдп рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рднреАрддрд░ рд╕рднреА рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рдкреНрд░рдЪрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛

рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ A рд╣реИ рдФрд░ A(undefined, {}) === Sa рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдФрд░ B(undefined, {}) === { a1: Sa, a2: Sa } рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд░реЗрдбреНрдпреВрд╕рд░ B B(undefined, {}) === { a1: Sa, a2: Sa } рдЬрд╣рд╛рдВ рдХреБрдВрдЬреА a1 рд╣реИ a2 A рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╣реИрдВред

['a1'] рдХреЗ рдирд╛рдо рд╕реНрдерд╛рди рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд░рд┐рдпрд╛ (* рдиреЗрдорд╕реНрдкреЗрд╕ рд╣рдореЗрд╢рд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рдПрд░реЗ рдХрд╛ рдЖрджреЗрд╢ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп рдХреА рдХреБрдВрдЬреА рдХреЗ рд╕рдорд╛рди рд╣реЛрддрд╛ рд╣реИ) B рдкрд░ рдХрд╛рд╕реНрдЯ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рдгрд╛рдо рджреЗрдЧрд╛

const action = {
  type: UNIQUE_ID,
  namespace: ['a1']
};

B(undefined, action) == { a1: A(undefined, action*), a2: Sa }

рдФрд░ рдмрд┐рдирд╛ рдирд╛рдорд╕реНрдерд╛рди рд╡рд╛рд▓реА рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдХрд╛рдЙрдВрдЯрд░ рдЙрджрд╛рд╣рд░рдг

const action = {
  type: UNIQUE_ID
};


B(undefined, action) == { a1: A(undefined, action), a2: A(undefined, action) }

рдЪреЗрддрд╛рд╡рдирд┐рдпрд╛рдВ

  • рдпрджрд┐ A рджреА рдЧрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╕рдВрднрд╛рд▓ рдирд╣реАрдВ рдкрд╛рддрд╛ рд╣реИ (рдпрд╣ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрддрд╛ рд╣реИ) рддреЛ рдЗрд╕реЗ рдЙрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП p рдЬреЛ рдХрд┐ рд░реЗрдбреНрдпреВрд╕рд░ рдХреЗ рд▓рд┐рдП рдЕрдкреНрд░рд╛рдкреНрдп рд╣реИ A B(undefined, p) рдХрд╛ рдкрд░рд┐рдгрд╛рдо $#$16 { a1: Sa, a2: Sa } B(undefined, p) рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд╕рдВрдпреЛрдЧ рд╕реЗ B рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рдорд╛рди рд╣реИ
  • рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ (рдКрдкрд░ action* рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд) рдХреЛ рдкрд╛рд╕ рдХреА рдЧрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рджрд╛рдпрд░реЗ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдирд╛рдо рд╕реНрдерд╛рди рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдХрд╛рд░реНрд░рд╡рд╛рдИ B рдХреЛ рдкрд╛рд╕ рдХреА рдЧрдИ рдереА рддреЛ рд╡рд╣ { type: UNIQUE_ID, namespace: ['a1'] } рдереА, рддреЛ A рддрдХ рдХреА рдЧрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ A { type: UNIQUE_ID, namespace: [] } рд╣реИ
  • рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреЛрд░ рдореЗрдВ рд╕рднреА рд░реЗрдбреНрдпреВрд╕рд░ рдХреЛ рдиреЗрдорд╕реНрдкреЗрд╕рд┐рдВрдЧ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрджрд┐ рдпрд╣ рдмрд┐рдВрджреБ рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЖрдк рдХрд┐рддрдиреЗ рдирд╛рдорд╕реНрдерд╛рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЖрдк рдХрд┐рддрдиреЗ рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ рдШреЛрдВрд╕рд▓рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЗрд╕рдХреА рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реИ

рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВ рдЖрдкрдХреЗ рд░реЗрдбреНрдпреВрд╕рд░ рдореЗрдВ рдиреЗрдорд╕реНрдкреЗрд╕ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЫрджреНрдо рдХреЛрдб рд▓реЗрдХрд░ рдЖрдпрд╛ рд╣реВрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рд░реЗрдбреНрдпреВрд╕рд░ рдХрд┐рд╕реА рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдореЗрдВ рдореМрдЬреВрдж рдЖрдВрд╢рд┐рдХ рд░реЗрдбреНрдпреВрд╕рд░ рдХреА рдорд╛рддреНрд░рд╛ред

(state = initialState, { ...action, namespace = [] }) => {
    var partialAction = { ...action, namespace: namespace.slice(1) };
    var newState;
    if (reducerCanHandleAction(reducer, action) and namespaceExistsInState(namespace, state)) {
        // apply the action to the matching partial reducer
        newState = {
            ...state,
            [namespace]: partialReducers[namespace](state[namespace], partialAction)
        };
    } else if (reducerCantHandleAction(reducer, action) {
        // apply the action to all partial reducers
        newState = Object.assign(
            {},
            state,
            ...Object.keys(partialReducers).map(
                namespace => partialReducers[namespace](state[namespace], action)
            )
        );
    } else {
        // can't handle the action
        return state;
    }

    return reducer(newState, action);
}

рдпрд╣ рдЖрдк рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛рдП рдХрд┐ рд░реЗрдбреНрдпреВрд╕рд░ рдкрд╣рд▓реЗ рд╕реЗ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рдореИрдВ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдореИрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░ рдХреБрдВрдЬреА рд╣реИрдВ рдФрд░ рд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдорд╛рди рд╣реИрдВред

рдореБрдЭреЗ рдЦреЗрд▓ рдореЗрдВ рдереЛрдбрд╝реА рджреЗрд░ рд╣реЛ рд╕рдХрддреА рд╣реИ рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдХреБрдЫ рд╕рд╛рдорд╛рдиреНрдп-рдЙрджреНрджреЗрд╢реНрдп рд╡рд╛рд▓реЗ рд░реЗрдбреНрдпреВрд╕рд░ рд▓рд┐рдЦреЗ рд╣реИрдВ рдЬреЛ рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
https://gist.github.com/crisu83/42ecffccad9d04c74605fbc75c9dc9d1

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореНрдпреВрдЯрд┐рд▓реНрд░реЗрдбреНрдпреВрд╕рд░ рдПрдХ рдорд╣рд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ

@jeffhtli рдорд▓реНрдЯреАрд░реЗрдбреНрдпреВрд╕рд░ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдорд╛рддреНрд░рд╛ рдореЗрдВ рд░реЗрдбреНрдпреВрд╕рд░ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдпрд╣ рдЖрдкрдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рд░реЗрдбреНрдпреВрд╕рд░ рд╕реВрдЪреА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддрд╛ рд╣реИ
рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдореИрдВрдиреЗ рдШрдЯрдХреЛрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдпреВрдпреВрдЖрдИрдбреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдпреВрдпреВрдЖрдИрдбреА рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рд╕реНрдерд┐рддрд┐ рдмрдирд╛рдИ
https://github.com/eloytoro/react-redux-uuid

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

dmitry-zaets picture dmitry-zaets  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ms88privat picture ms88privat  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

rui-ktei picture rui-ktei  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

timdorr picture timdorr  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

benoneal picture benoneal  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ