• [Redux] Reducer Composition with Arrays


    In the previous lesson we created a reducer that can handle two actions, adding a new to-do, and toggling an existing to-do. Right now, the code to update the to-do item or to create a new one is placed right inside of the to-dos reducer.

    This function is hard to understand because it makes us two different concerns, how the to-do's array is updated, and how individual to-dos are updated. This is not a problem unique to Redux. Any time a function does too many things, you want to extract other functions from it, and call them so that every function only addresses a single concern.

    In this case, I decided that creating and updating a to-do in response to an action is a separate operation, and needs to be handled by a separate function called to-do. As a matter of convention, I decided that it should also accept two arguments, the current trait and the action being dispatched, and it should return the next trait.

    But in this case, this trait refers to the individual to-do, and not to the least of to-dos. Finally, there is no magic in Redux to make it work. We extracted the to-do reducer from the to-dos reducer, so now we need to call it for every to-do, and assemble the results into an array.

    While this is not required in this particular example, I suggest that you always have the default case where you return the current trait to avoid all [inaudible 1:36] in the future. The part described in this lesson is pervasive in Redux's development, and is called reducer composition.

    Different reducers specify how different parts of the trait tree are updated in response to actions. Reducers are also normal JavaScript functions, so they can call other reducers to delegate and abstract a way of handling of updates of some parts of this tree they manage.

    This pattern can be applied many times, and while there is still a single top level reducer managing the state of your app, you will find it convenient to express it as many reducers call on each other, each contribution to a part of the applications trait tree.

    let todo = (state, action) => {
      switch(action.type){
          case 'ADD_ITEM':
            return {
              text: action.text,
              id: action.id,
              completed: false
            };
        case 'TOGGLE_ITEM': 
           if(state.id !== action.id){
              return state;
            }else{
             return {
              ...state,
              completed: !state.completed  // will overwirte the state object's completed prop
            };
           }
        default:
              return state;
      }
    }
    
    
    let todos = (state = [], action) => {
      
      switch(action.type){
        case 'ADD_ITEM':
          return state = [
            ...state,
            todo(undefined, action)
          ];
        case 'TOGGLE_ITEM':
          return state.map( (t) => todo(t, action))
        default:
          return state;
      }
    };
    
    let testTodo_addItem = () => {
      let stateBefore = [];
      let action = {
        type: 'ADD_ITEM',
        text: 'Learn Redux',
        id: 0
      };
      let stateAfter = [
        {
          text: 'Learn Redux',
          id: 0,
          completed: false,
        }
      ];
      
      deepFreeze(stateBefore);
      deepFreeze(action);
      
      expect(
        todos(stateBefore, action)
      ).toEqual(stateAfter);
    };
    
    let testTodo_toggleItem = () => {
      let stateBefore = [
        {
          text: 'Learn Redux',
          id: 0,
          completed: false
        },
        {
          text: 'Learn Angular2',
          id: 1,
          completed: false
        }
      ];
      let action = {
        type: 'TOGGLE_ITEM',
        id: 1
      };
      
      let stateAfter = [
        {
          text: 'Learn Redux',
          id: 0,
          completed: false
        },
        {
          text: 'Learn Angular2',
          id: 1,
          completed: true
        }
      ];
      
      deepFreeze(stateBefore);
      deepFreeze(action);
      
      expect(
        todos(stateBefore, action)
      ).toEqual(stateAfter);
    }
    
    testTodo_toggleItem();
    
    console.log("All tests passed!");
  • 相关阅读:
    SAP MM 启用批次管理的物料MB21创建预留单据时批次号可以为空!
    强化学习十大原则
    新手必看:生成对抗网络的初学者入门指导
    华为云总裁郑叶来:易获取、用得起、方便用的算力是人工智能发展的关键
    贝叶斯、香农、奥卡姆合写博客「机器学习是什么」
    诗人般的机器学习,ML工作原理大揭秘
    为什么AI的翻译水平还远不能和人类相比?
    2018-8-10-wpf-DoEvents-
    2018-2-13-win10-uwp-iot
    2019-9-11-.NET-Standard
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5011830.html
Copyright © 2020-2023  润新知