zoukankan      html  css  js  c++  java
  • [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!");
  • 相关阅读:
    高效能人士懂得忽视,知道怎样说“不”
    CheckBoxPreference组件
    SQL基础--> 约束(CONSTRAINT)
    html5--6-7 CSS选择器4
    html5--6-6 CSS选择器3
    html5--6-5 CSS选择器2
    html5--6-4 CSS选择器
    html5--6-3 CSS语法2
    html5--6-2 CSS语法
    html5--6-1 引入外部样式表
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5011830.html
Copyright © 2011-2022 走看看