批量更新规范化的Redux状态

时间:2017-11-13 16:57:16

标签: javascript reactjs redux

假设我已经像这样规范了状态(使用normalizr)

entities: {
  todos: {
    'aaa': {
      id: 'aaa',
      text: 'Todo A',
      completed: false
    },
    'bbb': {
      id: 'bbb',
      text: 'Todo B',
      completed: false
    },
    'ccc': {
      id: 'ccc',
      text: 'Todo C',
      completed: false
    }
  }
}

然后我有一个从服务器获取ID的操作,已完成。对于该动作类型,我有这样的reducer:

const todos = (state = initialState, action) => {
  switch (action.type) {
    case ActionTypes.FETCH_COMPLETED_SUCCESS:
      return {
        ...state,
        todos: action.payload.completedIds.map((id) => {
          return {
            [id]: {
              ...state.todos[id],
              completed: true
            }
          }
        })
      };
    default:
      return state;
  }
};

如果我收到一个带有''aaa','ccc']的数组(可能是真实应用程序中的数千个项目),我想在单个动作中将“completed”设置为TRUE,是吗?可能的?

我当前的reducer实现不起作用,因为它返回一个对象数组,而原始规范化状态是ID为关键字的对象。

感谢。

3 个答案:

答案 0 :(得分:3)

您可以将修改后的待办事项存储在对象中,然后使用扩展语法(如

)进行更新
const todos = (state = initialState, action) => {
  switch (action.type) {
    case ActionTypes.FETCH_COMPLETED_SUCCESS:
      let newTodos = {};
      action.payload.completedIds.forEach((id) => {
          newTodos[id]: {
              ...state.todos[id],
              completed: true
            }
          })
        })
      return {
        ...state,
        todos: {
             ...state.todos,
             ...newTodos
        }
      };
    default:
      return state;
  }
};

答案 1 :(得分:0)

我认为这是解决问题的方法:

const todos = (state = initialState, action) => {
  switch (action.type) {
    case ActionTypes.FETCH_COMPLETED_SUCCESS:
      return {
        ...state,
        todos: Object.keys(action.payload.completedIds).reduce((previous, current) => {
            previous[current] = {
              ...state.todos[current],
              completed: true
            }
            return previous;
          }, {})
        })
      };
    default:
      return state;
  }
};

我使用此解决方案,因为返回一个新对象并保留原始对象

答案 2 :(得分:0)

你可以试试这个:

 const todos = (state = initialState, action) => {
  switch (action.type) {
    case ActionTypes.FETCH_COMPLETED_SUCCESS:
      const newState = {};//New Object
      const filterKeys = Object.keys(state).filter( key=>{
        newState[key]=state[key]; //copy
        return completedIds.indexOf(key)!=-1;
      });
      filterKeys.forEach(key=> newState[key].completed = true);
       return newState;
    default:
      return state;
  }
};