【问题标题】:Bulk updating normalized Redux state批量更新标准化 Redux 状态
【发布时间】:2023-03-16 04:05:02
【问题描述】:

假设我有这样的标准化状态(使用 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 数组的操作,这些操作已完成。对于那种动作类型,我有这样的减速器:

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'] 的数组(在现实世界的应用程序中可能是数千个项目),我想在单个操作中将这些相应的待办事项上的“已完成”设置为 TRUE,是吗可能吗?

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

谢谢。

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    您可以将修改后的待办事项存储在一个对象中,然后使用扩展语法更新它,例如

    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;
      }
    };
    

    【讨论】:

    • 这行得通,只需要修复一个小的语法错误。 newTodos[id]: { ... } 到 newTodos[id] = { ... }
    【解决方案2】:

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

    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;
      }
    };
    

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

    【讨论】:

      【解决方案3】:

      你可以试试这个:

       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;
        }
      };
      

      【讨论】:

        猜你喜欢
        • 2017-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-22
        • 2017-10-21
        • 2016-11-22
        • 2017-03-03
        相关资源
        最近更新 更多