Обновить существующий элемент или добавить новый элемент в редуктор |Реагировать-Redux - PullRequest
1 голос
/ 08 ноября 2019

У меня есть требование, где я получу массив объектов. Я должен проверить, если полученный массив объектов уже присутствует в магазине. Если да, то я хочу обновить новый объект старым объектом, иначе я хочу добавить новый элемент в хранилище.

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 ]

1 голос
/ 08 ноября 2019

Как я понимаю, вы хотите объединить и заменить state.UserChangedData.changedData на action.payload на основе их значений идентификатора.

Вы можете использовать следующий редуктор для достижения того, что вы хотите:

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

Идея взята из этого поста:

Как объединить и заменить объекты из двух массивов на основе ключа в 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" }]
});
0 голосов
/ 08 ноября 2019

Посмотрите на Неизменяемые шаблоны обновления в документации Redux.

Ваш сценарий:

  • ваше состояние правильно инициализировано в пустой массив, следовательно, ваше state.UserChangedData.changedData - это всегда массив
  • в вашем case SET_USER_BUCKET_LIST_DATA:, вы должны создать новую переменную let newStateChangedData = [...state.UserChangedData.changedData]
  • для всех элементов в action.payload, и для каждого элемента загляните в state.UserChangedData.changedData, еслион есть
  • , затем всегда обновляйте свое состояние таким образом (if в вашем решении не должно быть):
return {
    ...state,
    UserChangedData: {
        ...state.UserChangedData,
        changedData: newStateChangedData
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...