Redux: рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╕рдордп рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреИрд╕реЗ рдХрд╛рдЯреЗрдВ?

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

рдЗрд╕рд▓рд┐рдП рдореЗрд░реЗ рдкрд╛рд╕ рдореЗрд░реЗ рд░рд╛рдЬреНрдп рдХреЗ рддрд╣рдд рдпрд╣ рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд░рдЪрдирд╛ рд╣реИ

state = {
   plans: [
    {title: 'A', exercises: [{title: 'exe1'}, {title: 'exe2'},{title: 'exe3'}]},
    {title: 'B', exercises: [{title: 'exe5'}, {title: 'exe1'},{title: 'exe2'}]}
   ]
}

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

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдореИрдВ рдПрдХ рдирдпрд╛ рдЦрд╛рд▓реА рдЕрднреНрдпрд╛рд╕ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдпрд╛ рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рддреЛ рдбреЗрдЯрд╛ рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдЬреЛ рдореИрдВ рдЕрднреА рдХрд░реВрдВрдЧрд╛:

state.plans[planIdx].exercises.push({})

state.plans[planIdx].exercises[exerciseIdx] = exercise

рд▓реЗрдХрд┐рди рдЗрд╕ рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд╡рд╣реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ? рдореИрдВрдиреЗ Redux рдбреЙрдХреНрд╕ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдирд┐рд╡рд╛рд░рдг рднрд╛рдЧ рдХреЛ рднреА рдкрдврд╝рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЬреЛ рдлреБрд░реНрд╕рдд рдорд┐рд▓реА, рдореИрдВ рдПрдХ рдпреЛрдЬрдирд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░ рд░рд╣рд╛ рдерд╛, рдЬрд╣рд╛рдБ рдореИрдВ рдХрд░реВрдБрдЧрд╛:

case 'UPDATE_PLAN':
    return {
      ...state,
      plans: [
      ...state.plans.slice(0, action.idx),
      Object.assign({}, state.plans[action.idx], action.plan),
      ...state.plans.slice(action.idx + 1)
      ]
    };

рдХреНрдпрд╛ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рддреЗрдЬрд╝ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ? рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рдореБрдЭреЗ рдмрд╛рд╣рд░реА рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдЕрдЧрд░ рдХреЛрдИ рдореБрдЭреЗ рд╕рдордЭрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рдмреЗрд╣рддрд░ рдХреИрд╕реЗ рдирд┐рдкрдЯреЗрдВ ...

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

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

рд╣рд╛рдВ, рд╣рдо рдЖрдкрдХрд╛ рдбреЗрдЯрд╛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВред
рдЗрд╕ рддрд░рд╣ рдЖрдкрдХреЛ "рдЧрд╣рд░реЗ" рдЬрд╛рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИ: рдЖрдкрдХреА рд╕рднреА рдЗрдХрд╛рдЗрдпрд╛рдБ рд╕рдорд╛рди рд╕реНрддрд░ рдкрд░ рд╣реИрдВред

рддреЛ рдЖрдкрдХрд╛ рд░рд╛рдЬреНрдп рдХреИрд╕рд╛ рд▓рдЧреЗрдЧрд╛

{
  entities: {
    plans: {
      1: {title: 'A', exercises: [1, 2, 3]},
      2: {title: 'B', exercises: [5, 1, 2]}
     },
    exercises: {
      1: {title: 'exe1'},
      2: {title: 'exe2'},
      3: {title: 'exe3'}
    }
  },
  currentPlans: [1, 2]
}

рдЖрдкрдХреЗ рд░рд┐рдбреНрдпреВрд╕рд░ рджрд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

import merge from 'lodash/object/merge';

const exercises = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...action.exercise
      }
    };
  case 'UPDATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.exercise
      }
    };
  default:
    if (action.entities && action.entities.exercises) {
      return merge({}, state, action.entities.exercises);
    }
    return state;
  }
}

const plans = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...action.plan
      }
    };
  case 'UPDATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.plan
      }
    };
  default:
    if (action.entities && action.entities.plans) {
      return merge({}, state, action.entities.plans);
    }
    return state;
  }
}

const entities = combineReducers({
  plans,
  exercises
});

const currentPlans = (state = [], action) {
  switch (action.type) {
  case 'CREATE_PLAN':
    return [...state, action.id];
  default:
    return state;
  }
}

const reducer = combineReducers({
  entities,
  currentPlans
});

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

рджреВрд╕рд░рд╛, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреИрд╕реЗ рд╣рдо plans reducer рдореЗрдВ рдПрдХ рдЙрдкрдпреБрдХреНрдд рдЗрдХрд╛рдИ рдЬреЛрдбрд╝рдХрд░ CREATE_PLAN рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ _and_ рдЕрдкрдиреА ID рдХреЛ currentPlans reducer рдореЗрдВ рдЬреЛрдбрд╝рдХрд░ред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдРрдкреНрд╕ рдореЗрдВ, рдЖрдкрдХреЗ рд╕рдВрдмрдВрдз рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ plans reducer ADD_EXERCISE_TO_PLAN рдХреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдкреНрд▓рд╛рди рдХреЗ рдЕрдВрджрд░ рд╕рд░рдгреА рдореЗрдВ рдПрдХ рдирдИ ID рдЬреЛрдбрд╝рдХрд░ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╡реНрдпрд╛рдпрд╛рдо рдЦреБрдж рд╣реА рдЕрдкрдбреЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ _there рдХреЛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП plans reducer рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ ID рдиреЗ_ рдирд╣реАрдВ рдмрджрд▓рд╛ рд╣реИред

рддреАрд╕рд░рд╛, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрдХрд╛рдЗрдпрд╛рдБ reducers ( plans рдФрд░ exercises ) action.entities рд▓рд┐рдП рдмрд╛рд╣рд░ рджреЗрдЦрдиреЗ рд╡рд╛рд▓реЗ рд╡рд┐рд╢реЗрд╖ рдЦрдВрдб рд╣реИрдВред рдРрд╕рд╛ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ "рдЬреНрдЮрд╛рдд рд╕рддреНрдп" рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рд╕рднреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдХрд┐рд╕реА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рднреЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдиреЙрд░реНрдорд┐рдЬрд╝рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рдЗрд╕реЗ Redux рд░реЗрдкреЛ рдореЗрдВ "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛" рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдВрдд рдореЗрдВ, рдиреЛрдЯрд┐рд╕ рдХрд░реЗрдВ рдХрд┐ рд░рд┐рдбреНрдпреВрд╕рд░ рдХреИрд╕реЗ рд╕рдорд╛рди рд╣реИрдВред рдЖрдк рдЙрдиреНрд╣реЗрдВ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдореЗрд░реЗ рдЙрддреНрддрд░ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ - рдХрднреА-рдХрднреА рдЖрдк рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛рдкрди рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдХрднреА-рдХрднреА рдЖрдк рдХрдо рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЖрдк "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛" рдЙрджрд╛рд╣рд░рдг reducers рдореЗрдВ рд╕рдорд╛рди reducers рдмрдирд╛рдиреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкреЗрдЬрд┐рдиреЗрд╢рди рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдУрд╣, рдФрд░ рдореИрдВрдиреЗ { ...a, ...b } рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдпрд╣ ES7 рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд░реВрдк рдореЗрдВ рдмрд╛рдмреЗрд▓ рдЪрд░рдг 2 рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред рдЗрд╕реЗ "рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдкреНрд░реЗрдб рдСрдкрд░реЗрдЯрд░" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ Object.assign({}, a, b) рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред

рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк Lodash рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХреЗ рдкреНрд░рддрд┐ рд╕рд╛рд╡рдзрд╛рди, рдЬреИрд╕реЗ рд╣реЛрдирд╛ merge({}, a, b} рд╕рд╣реА рд╣реИ рд▓реЗрдХрд┐рди merge(a, b) , рдирд╣реАрдВ рд╣реИ) updeep , рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдПрдбрдСрди рдЕрджреНрдпрддрди рдпрд╛ рдХреБрдЫ рдФрд░ред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЧрд╣рд░реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдорд╣рд╕реВрд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рд░рд╛рдЬреНрдп рд╡реГрдХреНрд╖ рдкрд░реНрдпрд╛рдкреНрдд рд╕рдкрд╛рдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдпрд╣ рдХрд┐ рдЖрдк рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдкрд░реНрдпрд╛рдкреНрдд рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЖрдкрдХрд╛ рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг:

case 'UPDATE_PLAN':
  return {
    ...state,
    plans: [
      ...state.plans.slice(0, action.idx),
      Object.assign({}, state.plans[action.idx], action.plan),
      ...state.plans.slice(action.idx + 1)
    ]
  };

рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

const plan = (state = {}, action) => {
  switch (action.type) {
  case 'UPDATE_PLAN':
    return Object.assign({}, state, action.plan);
  default:
    return state;
  }
}

const plans = (state = [], action) => {
  if (typeof action.idx === 'undefined') {
    return state;
  }
  return [
    ...state.slice(0, action.idx),
    plan(state[action.idx], action),
    ...state.slice(action.idx + 1)
  ];
};

// somewhere
case 'UPDATE_PLAN':
  return {
    ...state,
    plans: plans(state.plans, action)
  };

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

рдпрд╣ рдиреЗрд╕реНрдЯреЗрдб JSON рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╢рдВрд╕рд┐рдд рд╣реИ: https://github.com/gaearon/normalizr

рд╣рд╛рдВ, рд╣рдо рдЖрдкрдХрд╛ рдбреЗрдЯрд╛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВред
рдЗрд╕ рддрд░рд╣ рдЖрдкрдХреЛ "рдЧрд╣рд░реЗ" рдЬрд╛рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИ: рдЖрдкрдХреА рд╕рднреА рдЗрдХрд╛рдЗрдпрд╛рдБ рд╕рдорд╛рди рд╕реНрддрд░ рдкрд░ рд╣реИрдВред

рддреЛ рдЖрдкрдХрд╛ рд░рд╛рдЬреНрдп рдХреИрд╕рд╛ рд▓рдЧреЗрдЧрд╛

{
  entities: {
    plans: {
      1: {title: 'A', exercises: [1, 2, 3]},
      2: {title: 'B', exercises: [5, 1, 2]}
     },
    exercises: {
      1: {title: 'exe1'},
      2: {title: 'exe2'},
      3: {title: 'exe3'}
    }
  },
  currentPlans: [1, 2]
}

рдЖрдкрдХреЗ рд░рд┐рдбреНрдпреВрд╕рд░ рджрд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

import merge from 'lodash/object/merge';

const exercises = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...action.exercise
      }
    };
  case 'UPDATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.exercise
      }
    };
  default:
    if (action.entities && action.entities.exercises) {
      return merge({}, state, action.entities.exercises);
    }
    return state;
  }
}

const plans = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...action.plan
      }
    };
  case 'UPDATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.plan
      }
    };
  default:
    if (action.entities && action.entities.plans) {
      return merge({}, state, action.entities.plans);
    }
    return state;
  }
}

const entities = combineReducers({
  plans,
  exercises
});

const currentPlans = (state = [], action) {
  switch (action.type) {
  case 'CREATE_PLAN':
    return [...state, action.id];
  default:
    return state;
  }
}

const reducer = combineReducers({
  entities,
  currentPlans
});

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

рджреВрд╕рд░рд╛, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреИрд╕реЗ рд╣рдо plans reducer рдореЗрдВ рдПрдХ рдЙрдкрдпреБрдХреНрдд рдЗрдХрд╛рдИ рдЬреЛрдбрд╝рдХрд░ CREATE_PLAN рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ _and_ рдЕрдкрдиреА ID рдХреЛ currentPlans reducer рдореЗрдВ рдЬреЛрдбрд╝рдХрд░ред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдРрдкреНрд╕ рдореЗрдВ, рдЖрдкрдХреЗ рд╕рдВрдмрдВрдз рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ plans reducer ADD_EXERCISE_TO_PLAN рдХреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдкреНрд▓рд╛рди рдХреЗ рдЕрдВрджрд░ рд╕рд░рдгреА рдореЗрдВ рдПрдХ рдирдИ ID рдЬреЛрдбрд╝рдХрд░ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╡реНрдпрд╛рдпрд╛рдо рдЦреБрдж рд╣реА рдЕрдкрдбреЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ _there рдХреЛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП plans reducer рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ ID рдиреЗ_ рдирд╣реАрдВ рдмрджрд▓рд╛ рд╣реИред

рддреАрд╕рд░рд╛, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрдХрд╛рдЗрдпрд╛рдБ reducers ( plans рдФрд░ exercises ) action.entities рд▓рд┐рдП рдмрд╛рд╣рд░ рджреЗрдЦрдиреЗ рд╡рд╛рд▓реЗ рд╡рд┐рд╢реЗрд╖ рдЦрдВрдб рд╣реИрдВред рдРрд╕рд╛ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ "рдЬреНрдЮрд╛рдд рд╕рддреНрдп" рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рд╕рднреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдХрд┐рд╕реА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рднреЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдиреЙрд░реНрдорд┐рдЬрд╝рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рдЗрд╕реЗ Redux рд░реЗрдкреЛ рдореЗрдВ "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛" рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдВрдд рдореЗрдВ, рдиреЛрдЯрд┐рд╕ рдХрд░реЗрдВ рдХрд┐ рд░рд┐рдбреНрдпреВрд╕рд░ рдХреИрд╕реЗ рд╕рдорд╛рди рд╣реИрдВред рдЖрдк рдЙрдиреНрд╣реЗрдВ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдореЗрд░реЗ рдЙрддреНрддрд░ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ - рдХрднреА-рдХрднреА рдЖрдк рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛рдкрди рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдХрднреА-рдХрднреА рдЖрдк рдХрдо рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЖрдк "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛" рдЙрджрд╛рд╣рд░рдг reducers рдореЗрдВ рд╕рдорд╛рди reducers рдмрдирд╛рдиреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкреЗрдЬрд┐рдиреЗрд╢рди рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдУрд╣, рдФрд░ рдореИрдВрдиреЗ { ...a, ...b } рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдпрд╣ ES7 рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд░реВрдк рдореЗрдВ рдмрд╛рдмреЗрд▓ рдЪрд░рдг 2 рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред рдЗрд╕реЗ "рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдкреНрд░реЗрдб рдСрдкрд░реЗрдЯрд░" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ Object.assign({}, a, b) рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред

рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк Lodash рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХреЗ рдкреНрд░рддрд┐ рд╕рд╛рд╡рдзрд╛рди, рдЬреИрд╕реЗ рд╣реЛрдирд╛ merge({}, a, b} рд╕рд╣реА рд╣реИ рд▓реЗрдХрд┐рди merge(a, b) , рдирд╣реАрдВ рд╣реИ) updeep , рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдПрдбрдСрди рдЕрджреНрдпрддрди рдпрд╛ рдХреБрдЫ рдФрд░ред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЧрд╣рд░реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдорд╣рд╕реВрд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рд░рд╛рдЬреНрдп рд╡реГрдХреНрд╖ рдкрд░реНрдпрд╛рдкреНрдд рд╕рдкрд╛рдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдпрд╣ рдХрд┐ рдЖрдк рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдкрд░реНрдпрд╛рдкреНрдд рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЖрдкрдХрд╛ рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг:

case 'UPDATE_PLAN':
  return {
    ...state,
    plans: [
      ...state.plans.slice(0, action.idx),
      Object.assign({}, state.plans[action.idx], action.plan),
      ...state.plans.slice(action.idx + 1)
    ]
  };

рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

const plan = (state = {}, action) => {
  switch (action.type) {
  case 'UPDATE_PLAN':
    return Object.assign({}, state, action.plan);
  default:
    return state;
  }
}

const plans = (state = [], action) => {
  if (typeof action.idx === 'undefined') {
    return state;
  }
  return [
    ...state.slice(0, action.idx),
    plan(state[action.idx], action),
    ...state.slice(action.idx + 1)
  ];
};

// somewhere
case 'UPDATE_PLAN':
  return {
    ...state,
    plans: plans(state.plans, action)
  };

рдЗрд╕реЗ рдПрдХ рдиреБрд╕реНрдЦрд╛ рдореЗрдВ рдмрджрд▓рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рд╣рдо рдПрдХ рдХрдВрдмрди рдмреЛрд░реНрдб рдЙрджрд╛рд╣рд░рдг рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдпрд╣ рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХрджрдо рд╕рд╣реА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ "рд▓реЗрди" рдореЗрдВ рдЙрдирдХреЗ рдЕрдВрджрд░ "рдХрд╛рд░реНрдб" рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

@ (re0799 рдпрд╛ рдЖрдк рдмрд╕

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рд╣рдо рдПрдХ рдХрдВрдмрди рдмреЛрд░реНрдб рдЙрджрд╛рд╣рд░рдг рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдореИрдВрдиреЗ рдПрдХ рд▓рд┐рдЦрд╛

рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп.рдЬреЗрдПрд╕ рд╣рдореЗрд╢рд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИред рдпрд╣ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрджрд▓реЗ рдЧрдП рдиреЛрдб рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд░рд╛рдЬреНрдп рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдореВрд▓ рдиреЛрдб рдХреЗ рд╣реИрд╢ рдХрд╛ рдкреБрдирд░рд╛рд╡рд░реНрддрдХ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЬреЛ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЕрдбрд╝рдЪрди рдмрди рдЬрд╛рддрд╛ рд╣реИ (рдпрд╣ рдмрд╣реБрдд рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЗ рдирд╣реАрдВ рд╣реИ)ред рдЗрд╕рд▓рд┐рдП рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ Immutable.js рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХреБрдЫ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдмрдирд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред

рдЖрдкрдХреЗ рдЙрддреНрддрд░ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж @gaearon , рдмрдврд╝рд┐рдпрд╛ рд╡реНрдпрд╛рдЦреНрдпрд╛!

рдЗрд╕рд▓рд┐рдП, рдЬрдм рдЖрдк CREATE_PLAN рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╛рдпрд╛рдо рдмрдирд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЗрд╕реЗ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореБрдЭреЗ рдЗрд╕ рддрд░рд╣ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП? рдХреНрдпрд╛ рдореБрдЭреЗ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ 3 рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдЪрд╛рд╣рд┐рдП? CREATE_PLAN, CREATE_EXERCISE, ADD_EXERCISE_TO_PLAN рдореБрдЭреЗ рдпреЗ рдХреЙрд▓ рдХрд╣рд╛рдВ рд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдЧрд░ рдРрд╕рд╛ рд╣реИ?

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

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

рдЖрдк Redux Thunk рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрди рджреЛрдиреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

function createPlan(title) {
  return dispatch => {
    const planId = uuid();
    const exerciseId = uuid();

    dispatch({
      type: 'CREATE_EXERCISE',
      id: exerciseId,
      exercise: {
        id: exerciseId,
        title: 'Default'
      }
    });

    dispatch({
      type: 'CREATE_PLAN',
      id: planId,
      plan: {
        id: planId,
        exercises: [exerciseId],
        title
      }
    });
  };
}

рдлрд┐рд░, рдпрджрд┐ рдЖрдк Redux Thunk рдорд┐рдбрд▓рд╡реЗрдпрд░ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

store.dispatch(createPlan(title));

рддреЛ рдЪрд▓рд┐рдП рдмрддрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рд░рд┐рд╢реНрддреЛрдВ (рдкреЛрд╕реНрдЯ, рд▓реЗрдЦрдХ, рдЯреИрдЧ, рдЕрдЯреИрдЪрдореЗрдВрдЯ рдЖрджрд┐) рдХреЗ рд╕рд╛рде рдмреИрдХрдПрдВрдб рдкрд░ рдореЗрд░рд╛ рдПрдХ рдкреЛрд╕реНрдЯ рдПрдбрд┐рдЯрд░ рд╣реИред

рдореИрдВ currentPosts currentPlans рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рдорд╛рди рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдЬрд╛рдКрдБ? рдореИрдВ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХреБрдВрдЬреА рдореИрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА currentPosts рдореЗрдВ рдЕрдкрдиреА рдЗрд╕реА рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП entities.posts рдореЗрдВ mapStateToProps рд╕рдорд╛рд░реЛрд╣? currentPosts рдЫрдВрдЯрдиреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ?

рдХреНрдпрд╛ рдпрд╣ рд╕рдм рдПрдХ reducer рд░рдЪрдирд╛ рдореЗрдВ рд╣реИ?

рдореБрдЭреЗ рдпрд╣рд╛рдБ рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИ ...

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

рдореИрдВ рдХрд░рдВрдЯрдкреЙрд▓реНрд╕ рдХреА рд╡рд░реНрддрдорд╛рди рд╕рд░рдгреА рдХреЗ рд╕рдорд╛рди рдХрд░рдВрдЯрдкреЙрд╕реНрдЯ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдЬрд╛рдКрдБ? рдХреНрдпрд╛ рдореБрдЭреЗ currentPosts рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХреБрдВрдЬреА рдХреЛ рдЙрд╕рдХреЗ рд╕рдВрдмрдВрдзрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдореИрдк рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдХрд░реЗрдВрдЯрдкреЙрдЗрдВрдЯ рдХреЛ рдХреИрд╕реЗ рд╕реЙрд░реНрдЯ рдХрд░реЗрдВ?

рдпрд╣ рд╕рд╣реА рд╣реИред рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╕рдордп рдЖрдк рд╕рдм рдХреБрдЫ рдХрд░реЗрдВрдЧреЗред рдХреГрдкрдпрд╛ "рд╢реЙрдкрд┐рдВрдЧ рдХрд╛рд░реНрдЯ" рдФрд░ "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛" рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рдкрд░рд╛рдорд░реНрд╢ рдХрд░реЗрдВ рдЬреЛ Redux рд░реЗрдкреЛ рдХреЗ рд╕рд╛рде рдЖрддреЗ рд╣реИрдВред

рдзрдиреНрдпрд╡рд╛рдж, рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдбреЙрдХреНрд╕ рдкрд░ рдХрдореНрдкреНрдпреВрдЯрд┐рдВрдЧ рд╡реНрдпреБрддреНрдкрдиреНрди рдбреЗрдЯрд╛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рд╡рд┐рдЪрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИред

рдореИрдВ рдЙрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдлрд┐рд░ рд╕реЗ рдЬрд╛рдБрдЪ рдХрд░реВрдБрдЧрд╛ред рдЬрдм рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдкрдврд╝рддрд╛ рдерд╛ рддреЛ рдореБрдЭреЗ рдмрд╣реБрдд рдХреБрдЫ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рдерд╛ рдХрд┐ рдкрд╣рд▓реЗ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рдерд╛ред

@ andre0799

рдХрд┐рд╕реА рднреА connect() рдПрдб рдХрдВрдкреЛрдиреЗрдВрдЯ рдореЗрдВ dispatch рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░реЙрдк рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

this.props.dispatch(createPlan(title));

рдпрд╣ рдПрдХ рдЙрдкрдпреЛрдЧ рдкреНрд░рд╢реНрди рд╣реИ рдЬреЛ рдЗрд╕ рдереНрд░реЗрдб рд╕реЗ рдЕрд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рдкрд░рд╛рдорд░реНрд╢ рдХрд░рдирд╛ рдпрд╛ рдЗрд╕рдХреЗ рд▓рд┐рдП StackOverflow рдкреНрд░рд╢реНрди рдмрдирд╛рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред

рдореИрдВ рдбреЗрдЯрд╛ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рдиреЗ рдФрд░ рдпрдерд╛рд╕рдВрднрд╡ рд░рд╛рдЬреНрдп рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕рдорддрд▓ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдбреИрди рд╕реЗ рд╕рд╣рдордд рд╣реВрдВред рдЗрд╕реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдореЗрдВ рдПрдХ рдиреБрд╕реНрдЦрд╛ / рд╕рд░реНрд╡реЛрддреНрддрдо рдЕрднреНрдпрд╛рд╕ рдХреЗ рд░реВрдк рдореЗрдВ рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдиреЗ рдореБрдЭреЗ рдХреБрдЫ рд╕рд┐рд░рджрд░реНрдж рд╕реЗ рдмрдЪрд╛рдпрд╛ рд╣реЛрдЧрд╛ред

рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд░рд╛рдЬреНрдп рдореЗрдВ рдереЛрдбрд╝реА рдЧрд╣рд░рд╛рдИ рд╣реЛрдиреЗ рдХреА рдЧрд▓рддреА рдХреА рд╣реИ, рдореИрдВрдиреЗ Redux рдХреЗ рд╕рд╛рде рдЧрд╣рд░реА рд╕реНрдерд┐рддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдФрд░ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рджрд╛рдпрд┐рддреНрд╡ рдмрдирд╛рдпрд╛: https://github.com/baptistemanson/immutable-path
рд╢рд╛рдпрдж рдореБрдЭреЗ рдпрд╣ рд╕рдм рдЧрд▓рдд рд▓рдЧрд╛ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЖрдкрдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реЛрдЧреАред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░реЗрдЧрд╛ред

рдпрд╣ рдорджрджрдЧрд╛рд░ рдерд╛ред рд╕рднреА рдХреЛ рдзрдиреНрдпрд╡рд╛рджред

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рдорд╛рди рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдХрд┐рд╕реА рдпреЛрдЬрдирд╛ рдореЗрдВ рд╡реНрдпрд╛рдпрд╛рдо рдХреЛ рдХреИрд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ? рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдПрдХ рд╡реНрдпрд╛рдпрд╛рдо рдЬреЛрдбрд╝рдиреЗ рд╕реЗ planId рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде, рдирдИ рдмрдирд╛рдИ рдЧрдИ рд╡реНрдпрд╛рдпрд╛рдо рдЗрдХрд╛рдИ рд╡рд╛рдкрд╕ рдЖ рдЧрдИред рдХреНрдпрд╛ рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ reducer рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд┐рдирд╛ рдЙрд╕ рдпреЛрдЬрдирд╛ рдореЗрдВ рдирдпрд╛ рдЕрднреНрдпрд╛рд╕ рдЬреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ CREATE_EXERCISE рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП рд╕реБрдиреЛ?

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

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: рдХреНрд▓рд╛рдЗрдВрдЯ рдиреЗрд╕реНрдЯреЗрдб рдПрдХреНрд╕рд░рд╕рд╛рдЗрдЬ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ -> рдХреНрд▓рд╛рдЗрдВрдЯ рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ redux рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИ -> рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдбреЗрдЯрд╛ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХрд░рддрд╛ рд╣реИ -> рдпреВрдЬрд░ рдХреНрд▓рд┐рдХреНрд╕ рд╕реЗрд╡ -> рдХреНрд▓рд╛рдЗрдВрдЯ рдРрдк рдЕрдкрдбреЗрдЯреЗрдб рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдбреЗрдЯрд╛ рдХреЛ n n рдлреЙрд░реНрдо рдореЗрдВ рд╡рд╛рдкрд╕ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЗрд╕реЗ рд░рд┐рдореЛрдЯ рд╕рд░реНрд╡рд░ рдкрд░ рдЬрдорд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ -> рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд░реНрд╡рд░ рдХреЛ рд╕рдмрдорд┐рдЯ рдХрд░рддрд╛ рд╣реИ

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

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

рд╡рд╣рд╛рдБ рдХреБрдЫ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ https://github.com/gpbl/denormalizr рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕рд╛рдорд╛рдиреНрдп рдЕрдкрдбреЗрдЯ рдХреЛ рдХрд┐рддрдиреА рдмрд╛рд░реАрдХреА рд╕реЗ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЬрд┐рд╕ рдРрдк рдкрд░ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ, рдЙрд╕рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдХреБрдЫ рдШрдВрдЯреЛрдВ рдореЗрдВ рдиреЙрд░реНрдорд┐рдЬрд╝рд░ рд▓рд┐рдЦрд╛, рдЖрдк рдЗрд╕рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

рдХреВрд▓ рдореИрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рдпреЛрдЧ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реВрдВрдЧрд╛ рдФрд░ рдХреБрдЫ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╡рд╛рдкрд╕ рдпреЛрдЧрджрд╛рди рджреВрдВрдЧрд╛ред рдХреБрдЫ рдШрдВрдЯреЛрдВ рдХреЗ рд▓рд┐рдП рдорд╣рд╛рди рдХрд╛рдо ;-) рдореЗрд░реЗ рдкрд╛рд╕ рд╡рд╛рдкрд╕ рдЖрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдореИрдВ рдЧрд╣рд░реА рдиреЗрд╕реНрдЯреЗрдб рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реВрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВрдиреЗ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп.рдЬреЗрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрд╢реАрд▓ рд╕рдорд╛рдзрд╛рди рдкрд╛рдпрд╛ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдареАрдХ рд╣реИ рдЕрдЧрд░ рдореИрдВ рдПрдХ StackOverflow рдкреЛрд╕реНрдЯ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реВрдВ рдЬреЛ рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рд╕рдорд╛рдзрд╛рди рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдкреВрдЫ рд░рд╣рд╛ рд╣реИ?

рдореИрдВ рдЗрд╕реЗ рдЕрднреА рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдХреГрдкрдпрд╛ рдореЗрд░реА рдкреЛрд╕реНрдЯ рд╣рдЯрд╛рдПрдВ рдпрд╛ рдХрд╣реЗрдВ рдХрд┐ рдпрд╣рд╛рдВ рд▓рд┐рдВрдХ рдХрд░рдирд╛ рдЕрдиреБрдЪрд┐рдд рд╣реИ:
http://stackoverflow.com/questions/37171203/manipulating-data-in-nested-arrays-in-redux-with-immutable-js

рдореИрдВрдиреЗ рджреЗрдЦрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдЕрддреАрдд рдореЗрдВ рдЕрдиреБрд╢рдВрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЬрдм рдХреЛрдИ рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдирд┐рдХрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, reducer рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рднреА рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдПрдХ рдСрдкрд░реЗрд╢рди рдЬреЛ рдУ (рдПрди) рд╣реЛрдЧрд╛, рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗред рдХрд┐рд╕реА рдХреЛ рднреА рдЗрд╕реА рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ рдФрд░ рдЗрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛?

@ariofrio : рдЖрд╣ ... рдореИрдВ рдЙрд▓рдЭрди рдореЗрдВ рд╣реВрдБред рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдХреА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ _not_ рд╕рдВрдЧреНрд░рд╣реАрдд рдиреЗрд╕реНрдЯреЗрдб рд╣реИрдВ, рдФрд░ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдЖрдЗрдЯрдо рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрджрд░реНрдн рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЙрд╕ рдЖрдЗрдЯрдо рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдм, рдЕрдЧрд░ рд╡рд╣рд╛рдБ рдХрдИ рдЕрдиреНрдп рд╕рдВрд╕реНрдерд╛рдПрдВ рд╣реИрдВ рдЬреЛ рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рдЗрд╕ рдЖрдЗрдЯрдо рдХреЛ "рд╕рдВрджрд░реНрднрд┐рдд" рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЙрдиреНрд╣реЗрдВ рдЙрд╕реА рддрд░рд╣ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕реЗ рдХрд┐ рдЪреАрдЬреЗрдВ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдирд╣реАрдВ рдереАрдВред

рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЪрд┐рдВрддрд╛ рд╣реИ, рдпрд╛ рдПрдХ рдкрд░реЗрд╢рд╛рдиреА рд╡рд╛рд▓рд╛ рдкрд░рд┐рджреГрд╢реНрдп рдЬреЛ рдЖрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ?

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

{
  entities: {
    plans: {
      1: {title: 'A', exercises: [1, 2, 3]},
      2: {title: 'B', exercises: [5, 6]}
     },
    exercises: {
      1: {title: 'exe1'},
      2: {title: 'exe2'},
      3: {title: 'exe3'}
      5: {title: 'exe5'}
      6: {title: 'exe6'}
    }
  },
  currentPlans: [1, 2]
}

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдЕрднреНрдпрд╛рд╕ рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдпреЛрдЬрдирд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ "рд╡реНрдпрд╛рдпрд╛рдо рд╣рдЯрд╛рдПрдВ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╕рдВрджреЗрд╢ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддрд╛ рд╣реИ:

{type: "REMOVE_EXERCISE", payload: 2}

рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдареАрдХ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рднреА рдХреЛ рд╕рднреА рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдФрд░ рдлрд┐рд░ рдкреНрд░рддреНрдпреЗрдХ рдпреЛрдЬрдирд╛ рдХреЗ рднреАрддрд░ рд╕рднреА рдЕрднреНрдпрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрд┐рд╕реЗ рдПрдХ рдЭрдВрдЭрдЯ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдИрдбреА 2 рдХреЗ рд╕рд╛рде рд╡реНрдпрд╛рдпрд╛рдо рдХрд╛ рд╕рдВрджрд░реНрдн рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдУ (рдПрди) рдСрдкрд░реЗрд╢рди рд╣реИ рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореИрдВ рдЪрд┐рдВрддрд┐рдд рдерд╛ред

рдЗрд╕рд╕реЗ рдмрдЪрдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпреЛрдЬрдирд╛ рдЖрдИрдбреА рдХреЛ REMOVE_EXERCISE рдХреЗ рдкреЗрд▓реЛрдб рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдореБрдЭреЗ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдШреЛрдВрд╕рд▓реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рдлрд╛рдпрджрд╛ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред рдпрджрд┐ рд╣рдордиреЗ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдиреЗрд╕реНрдЯреЗрдб рд░рд╛рдЬреНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд░рд╛рдЬреНрдп рдРрд╕рд╛ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:

{
   plans: [
    {title: 'A', exercises: [{title: 'exe1'}, {title: 'exe2'},{title: 'exe3'}]},
    {title: 'B', exercises: [{title: 'exe5'}, {title: 'exe6'}]}
   ]
}

рдФрд░ рд╡реНрдпрд╛рдпрд╛рдо рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрджреЗрд╢ рдХреА рддрд░рд╣ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ:

{type: "REMOVE_EXERCISE", payload: {plan_index: 0, exercise_index: 1}}

рдХреБрдЫ рд╡рд┐рдЪрд╛рд░:

  • рдЖрдк рдЙрд╕ рдкрд░рд┐рджреГрд╢реНрдп рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдЕрднреНрдпрд╛рд╕реЛрдВ рдХрд╛ рдПрдХ рд░рд┐рд╡рд░реНрд╕ рд▓реБрдХрдЕрдк рдмрдирд╛рдП рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕реА рддрд░рд╣, рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд▓рд┐рдП Redux-ORM рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЬреЛ "рдЯреЗрдмрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ" рдСрдЯреЛ-рдЬреЗрдирд░реЗрдЯ рдХрд░рддреА рд╣реИред рддреЛ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЖрдкрдХреЗ рд╕реНрдЯреЛрд░ рдореЗрдВ рдПрдХ "PlanExercise" "рдЯреЗрдмрд▓" рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ {id, planId, exerciseId} рдЯреНрд░рд┐рдкрд▓ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗред рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдУ (рдПрди) рд╕реНрдХреИрди, рд▓реЗрдХрд┐рди рдПрдХ рд╕реАрдзрд╛ред
  • O (n) рдСрдкрд░реЗрд╢рди рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рдмреБрд░реА рдЪреАрдЬ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЗрд╕ рдмрд╛рдд рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдПрди рдХрд┐рддрдирд╛ рдмрдбрд╝рд╛ рд╣реИ, рд╢рдмреНрдж рдХреЗ рд╕рд╛рдордиреЗ рд╕реНрдерд┐рд░ рдХрд╛рд░рдХ, рдпрд╣ рдХрд┐рддрдиреА рдмрд╛рд░ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдФрд░ рдХреНрдпрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИред 10 рдпрд╛ 15 рдЖрдЗрдЯрдореЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХрд░рдирд╛ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдЯрди рдкрд░ рдХреБрдЫ рд╕рдорд╛рдирддрд╛ рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдмрд╛рдд рд╣реЛрдиреЗ рдЬрд╛ рд░рд╣реА рд╣реИ, рдХрд╣рддреЗ рд╣реИрдВ, рд╣рд░ 500ms рдореЗрдВ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реА 10M рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░рдирд╛ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдорд╣рдВрдЧрд╛ рдСрдкрд░реЗрд╢рди рдХрд░рдирд╛ рдЖрдЗрдЯрдоред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдСрдбреНрд╕ рд╣реИрдВ рдХрд┐ рд╣рдЬрд╛рд░реЛрдВ рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рд╛рд░реНрдердХ рдЕрдбрд╝рдЪрди рдирд╣реАрдВ рд╣реЛрдЧреАред
  • рдХреНрдпрд╛ рдпрд╣ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рджрд░реНрд╢рди рдЪрд┐рдВрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВ, рдпрд╛ рдХреЗрд╡рд▓ рд╕рдВрднрд╛рд╡рд┐рдд рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рдореБрджреНрджреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВ?

рдЕрдВрддрддрдГ, рджреЛрдиреЛрдВ рдиреЗрд╕реНрдЯреЗрдб рдФрд░ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд░рд╛рдЬреНрдп рдХрдиреНрд╡реЗрдВрд╢рди рд╣реИрдВред Redux рдХреЗ рд╕рд╛рде рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЕрдЪреНрдЫреЗ рдХрд╛рд░рдг рд╣реИрдВ, рдФрд░ рдЖрдкрдХреЗ рд░рд╛рдЬреНрдп рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреЗ рдХрд╛рд░рдг рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЬреЛ рднреА рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЙрдард╛рдУ :)

рдЗрд╕ рддрд░рд╣ рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди:

function deepCombinReducer(parentReducer, subReducer) {
    return function (state = parentReducer(void(0) /* get parent reducer initial state */, {}) {
        let finalState = {...state};

        for (var k in subReducer) {
          finalState[k] = subReducer(state[k], action);
        }

       return parentReducer(finalState, action);
    };
}

const parentReducer = function(state = {}, action) {
    return state;
}

const subReducer = function(state = [], action) {
    state = Immutable.fromJS(state).toJS();
    switch(action.type) {
       case 'ADD':
          state.push(action.sub);
           return state;
       default:
          return state;
   }
}

export default combineReducers({
   parent: deepCombinReducer(parentReducer, {
       sub: subReducer
   })
})

рдлрд┐рд░, рдЖрдк рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕реНрдЯреЛрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

{
    parent: {
       sub: []
    }
}

dispatch({
    type: 'ADD',
    sub: '123'
});

// the store will change to:
{
    parent: {
       sub: ['123']
    }
}

@smashercosmo immutable.js рдЧрд╣рд░реА рдиреЗрд╕реНрдЯреЗрдб рдЕрд╡рд╕реНрдерд╛ рдХреЗ рд╕рд╛рде? рдореИрдВ рдЙрддреНрд╕реБрдХ рд╣реВрдВ рдХрд┐ рдХреИрд╕реЗ

@gaearon

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрднреА рднреА рдЕрдиреНрдп рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рдЕрдВрджрд░ рдХреА рд╕рдВрд╕реНрдерд╛рдПрдВ рдирд╣реАрдВ рд╣реИрдВред

рдореИрдВ рдЗрд╕реЗ рдирд╣реАрдВ рд╕рдордЭрддрд╛ред рд╣рдорд╛рд░реЗ рдпрд╣рд╛рдВ рдХрдо рд╕реЗ рдХрдо рддреАрди рд╕реНрддрд░ рдХреЗ рдШреЛрдВрд╕рд▓реЗ рд╣реИрдВ:

{
  entities: {
    plans: {
      1: {title: 'A', exercises: [1, 2, 3]},
      2: {title: 'B', exercises: [5, 1, 2]}
     },
    exercises: {
      1: {title: 'exe1'},
      2: {title: 'exe2'},
      3: {title: 'exe3'}
    }
  },
  currentPlans: [1, 2]
}

entities.plans[1] - three levels
entities.exercises[1] - three levels

рдпрд╣ рдПрдХ рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╣реАрдВ рд╣реИред рдХреЗрд╡рд▓ рдПрдХ рд╕реНрддрд░ред

{
   plans: [1,2, 3],
   exercises: [1,2,3],
   'so forth': [1,2,3]
}

@wzup : FYI рдХрд░реЗрдВ, Dan рдЗрди рджрд┐рдиреЛрдВ Redux рдХреЗ рдореБрджреНрджреЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рдореЗрдВ рдЬреНрдпрд╛рджрд╛ рд╕рдордп рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ - рд╡рд╣ рд░рд┐рдПрдХреНрдЯ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЕрдкрдиреА рдкреНрд▓реЗрдЯ рдкрд░ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред

рдпрд╣рд╛рдВ "рдиреЗрд╕реНрдЯрд┐рдВрдЧ" рдХрд╛ рдЕрд░реНрде рд╣реИ рдЬрдм рдбреЗрдЯрд╛ рд╕реНрд╡рдпрдВ рдиреЗрд╕реНрдЯреЗрдб рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдереНрд░реЗрдб рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рдпрд╣ рдЙрджрд╛рд╣рд░рдг:

{
   plans: [
    {title: 'A', exercises: [{title: 'exe1'}, {title: 'exe2'},{title: 'exe3'}]},
    {title: 'B', exercises: [{title: 'exe5'}, {title: 'exe6'}]}
   ]
}

рдЙрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╡реНрдпрд╛рдпрд╛рдо "рдПрдХреНрд╕рдИ 6" рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдЦреБрджрд╛рдИ рдХрд░рдирд╛ рд╣реИ, рдЬреИрд╕реЗ plans[1].exercises[2] ред

рдореБрдЭреЗ @tmonte рдХреЗ рд╕рд╡рд╛рд▓ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ:

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рдорд╛рди рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдХрд┐рд╕реА рдпреЛрдЬрдирд╛ рдореЗрдВ рд╡реНрдпрд╛рдпрд╛рдо рдХреЛ рдХреИрд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ? рдорд╛рди рд▓реЗрдВ рдХрд┐ рдПрдХ рд╡реНрдпрд╛рдпрд╛рдо рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдПрдХ рдпреЛрдЬрдирд╛рдмрджреНрдз рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рд╛рде рдирд╡ рдирд┐рд░реНрдорд┐рдд рд╡реНрдпрд╛рдпрд╛рдо рдЗрдХрд╛рдИ рд╡рд╛рдкрд╕ рдЖ рдЧрдИред рдХреНрдпрд╛ рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ reducer рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд┐рдирд╛ рдЙрд╕ рдпреЛрдЬрдирд╛ рдореЗрдВ рдирдпрд╛ рдЕрднреНрдпрд╛рд╕ рдЬреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдПрдХ CREATE_EXITEF рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП рд╕реБрдиреЛ?

рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрдИ рд╕рдВрд╕реНрдерд╛рдПрдВ рд╣реИрдВ, рддреЛ рдкреНрд░рддреНрдпреЗрдХ рдЗрдХрд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ reducer рдмрдирд╛рдирд╛ рджрд░реНрджрдирд╛рдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЗрд╕реЗ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдореБрдЭреЗ рдЕрдм рддрдХ рдЗрд╕рдХрд╛ рдХреЛрдИ рд╣рд▓ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИред

рдореИрдВ presonnaly рдХрд╛ рдЙрдкрдпреЛрдЧ mergeWith рдХреЗ рдмрдЬрд╛рдп merge рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реЗрдкрди рдХреЗ рд▓рд┐рдП:

import mergeWith from 'lodash/mergeWith';

// Updates an entity cache in response to any action with `entities`.
function entities(state = {}, action) {
  // Here where we STORE or UPDATE one or many entities
  // So check if the action contains the format we will manage
  // wich is `payload.entities`
  if (action.payload && action.payload.entities) {
    // if the entity is already in the store replace
    // it with the new one and do not merge. Why?
    // Assuming we have this product in the store:
    //
    // products: {
    //   1: {
    //     id: 1,
    //     name: 'Awesome product name',
    //     rateCategory: 1234
    //   }
    // }
    //
    // We will updated with
    // products: {
    //   1: {
    //     id: 1,
    //     name: 'Awesome product name',
    //   }
    // }
    //
    // The result if we were using `lodash/merge`
    // notice the rate `rateCategory` hasn't changed:
    // products: {
    //   1: {
    //     id: 1,
    //     name: 'Awesome product name',
    //     rateCategory: 1234
    //   }
    // }
    // for this particular use case it's safer to use
    // `lodash/mergeWith` and skip the merge
    return mergeWith({}, state, action.payload.entities, (oldD, newD) => {
      if (oldD && oldD.id && oldD.id === newD.id) {
        return newD;
      }
      return undefined;
    });
  }

  // Here you could register other handlers to manipulate 
  // the entities
  switch (action.type) {
    case ActionTypes.SOME_ACTION:
      // do something;
    default:
      return state;
  }
}

const rootReducer = combineReducers({
  entities,
});
export default rootReducer;
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

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

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

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

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

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

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