更新现有项目或将新项目添加到reducer | React-Redux

时间:2019-11-08 07:42:03

标签: reactjs redux react-redux

我有一个接收对象数组的要求。我必须检查接收到的对象数组是否已经存在于商店中。如果是,那么我想用旧对象更新新对象,否则我想将新元素添加到存储中。

const initialState = {
    ....
    ....
    UserChangedData : {
        ....
        ....
        changedData: []
    }
}

export default function (state = initialState, action) {
    switch(action.type) {
        ....
        ....
        ....
        case SET_USER_BUCKET_LIST_DATA:
            // if there is no userChangedData this condition will run initially
            if (state.UserChangedData.changedData.length === 0) {
                return {
                    ...state,
                    UserChangedData: {
                        ...state.UserChangedData,
                        changedData: [...action.payload]
                    }
                };
            }

            // check if the user item already exists update them. if user item doesn't exists then add 
            // item to UserChangedData's changedData array with existing data. to check if the item 
            // exists or not we can use id.

           // the object which I receive will be an array of object(s)

            // scenario 1 Initial data.
           // [{id:1 , name: "john", gender: "Male"}, {id:2 , name: "peter", gender: "Male"}, {id:3 , 
           //  name: "Natalie", gender: "Female"}, {id:4 , name: "Nicole", gender:"Female"}]

            // scenario 2 : user edited one object with id 1 so update the whole object where the inital 
           // changedData  
           //  example data : [{id:1 , name: "Logan", gender: "Male"}]

           // scenario 3: user edited id: 1  and added a new object with id: 8 so update previous id: 1 
           // with new id: 1 object data and also add new object id: 8 data to changedData array.
           // id: 8 
           // example data: [{id:1 , name: "Jane", gender: "Female"}, {id:8 , name: "Jane", 
           //                 gender:"Female"}

我已经尝试了许多逻辑,但没有一个奏效,任何人都可以向我建议上述情况的逻辑。

2 个答案:

答案 0 :(得分:1)

据我了解,您想根据其ID值将state.UserChangedData.changedData合并为action.payload。

您可以使用以下reducer实现您想要的:

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_USER_BUCKET_LIST_DATA:
      let updatedChangeData = Object.values(
        []
          .concat(state.UserChangedData.changedData, action.payload)
          .reduce(
            (r, c) => ((r[c.id] = Object.assign(r[c.id] || {}, c)), r),
            {}
          )
      );

      return {
        ...state,
        UserChangedData: {
          ...state.UserChangedData,
          changedData: updatedChangeData
        }
      };

    default:
      return state;
  }
};

这个想法来自这篇文章:

How to merge and replace objects from two arrays based on a key in javascript?

以下是完整的代码,可在独立的节点应用程序中使用它:

const redux = require("redux");
const createStore = redux.createStore;

const SET_USER_BUCKET_LIST_DATA = "SET_USER_BUCKET_LIST_DATA";

const initialState = {
  UserChangedData: {
    changedData: []
  }
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_USER_BUCKET_LIST_DATA:
      let updatedChangeData = Object.values(
        []
          .concat(state.UserChangedData.changedData, action.payload)
          .reduce(
            (r, c) => ((r[c.id] = Object.assign(r[c.id] || {}, c)), r),
            {}
          )
      );

      return {
        ...state,
        UserChangedData: {
          ...state.UserChangedData,
          changedData: updatedChangeData
        }
      };

    default:
      return state;
  }
};

const store = createStore(rootReducer);

store.subscribe(() => {
  console.log("[Subscription]", store.getState().UserChangedData.changedData);
});

store.dispatch({
  type: SET_USER_BUCKET_LIST_DATA,
  payload: [{ id: 1, title: "A" }]
});

store.dispatch({
  type: SET_USER_BUCKET_LIST_DATA,
  payload: [{ id: 2, title: "B" }]
});

store.dispatch({
  type: SET_USER_BUCKET_LIST_DATA,
  payload: [{ id: 1, title: "AA" }]
});

答案 1 :(得分:0)

查看Redux文档中的Immutable Update Patterns

您的情况:

  • 您的状态已正确初始化为空数组,因此您的<TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" <!-- modify below line like below --> android:padding="5dp" /> 始终是数组
  • 在您的state.UserChangedData.changedData中,您应该创建新变量case SET_USER_BUCKET_LIST_DATA:
  • 循环遍历let newStateChangedData = [...state.UserChangedData.changedData]中的所有项目,并为每个项目查找action.payload(如果存在)
  • 然后总是以这种方式更新您的状态(解决方案中的newStateChangedData不应该存在):
if