Как правильно обновлять состояние магазина Redux в приложении React? - PullRequest
0 голосов
/ 13 мая 2019

У меня есть приложение React, которое использует Redux для управления состоянием. Первоначальная структура магазина выглядит следующим образом:

const initialState = fromJS({
  visitorRecords: [],
  approvedBookingId: null,
});

В какой-то момент мой visitorRecords становится примерно таким:

[  
   Map {  
      "id":"1556008644569",
      "expectedArrival":"Thu, 25 Apr 2019 08:31:00 GMT",
      "lastName":"Vath",
      "notes":"",
      "actualDeparture":"",
      "actualArrival":"",
      "visitor":"Sven Vath",
      "status":2,
      "cardNumber":2,
      "employeeBeingVisited":"John Doe",
      "firstName":"Sven",
      "expectedDeparture":"Fri, 26 Apr 2019 08:31:00 GMT",
      "verbalStatus":"Visitor returned pass",
      "company":"Disney"
   },
   Map {  
      "id":"1555586876781",
      "expectedArrival":"Thu, 18 Apr 2019 06:30:00 GMT",
      "lastName":"A.",
      "notes":"",
      "actualDeparture":"",
      "actualArrival":"",
      "visitor":"Christoph.",
      "status":0,
      "cardNumber":1,
      "employeeBeingVisited":"Jean Pier",
      "firstName":"Pablo",
      "expectedDeparture":"Sat, 20 Apr 2019 15:30:00 GMT",
      "verbalStatus":"Waiting for visitor arrival",
      "company":"Disney"
   }
]

Что я хочу сделать в своем редукторе, это обновить конкретную запись по ее идентификатору. У меня есть идентификатор и значения для полей редактирования, полученные из моего действия, но я не знаю, как с ними обращаться, следуя рекомендациям по обновлению.

Вот так выглядит мой редуктор:

export default (state = initialState, action) => {
  switch (action.type) {
    case ON_VISITOR_RECORDS_FETCHED:
      return state.merge({
        visitorRecords: fromJS(action.visitorRecords),
      });
    case ON_RETURN_APPROVED:
      return state.merge({
        approvedBookingId: action.approvedBookingId,
      });
    case ON_VISITOR_RECORD_UPDATED:
      console.log(JSON.stringify(state.get("visitorRecords")));
      // console.log('action.bookingBeingUpdated: ' + action.bookingBeingUpdated)
      // console.log('JSON.stringify(action.updatedTextFields)' + JSON.stringify(action.updatedTextFields))
      // console.log('updatedExpectedArrival: ' + action.updatedExpectedArrival)
      // console.log('updatedExpectedDeparture: ' + action.updatedExpectedDeparture)
      // console.log('updatedStatus: ' + action.updatedStatus)
      return state;
    default:
      return state;
  }
};

Здесь я хочу использовать action.bookingBeingUpdated , затем найти соответствующую запись в visitorRecords и обновить ее новыми action.updatedTextFields, action.updatedExpectedArrival, action.updatedExpectedDeparture, action.updatedStatus

Я читал эту статью, но я не совсем понимаю, как там происходит обновление. Плюс, структура контейнера там другая.

EDIT : Тип элементов в visitorRecords, кроме не анонимного объекта, а карты

Ответы [ 5 ]

1 голос
/ 13 мая 2019

Вот как вы будете использовать immutablejs

case ON_VISITOR_RECORD_UPDATED:
    const newRecordsCollection = visitorRecords.map(record => {
        if (record.get('id') === action.bookingBeingUpdated) {
            return record.merge({
                updatedTextFields: action.updatedTextFields, 
                updatedExpectedArrival: action.updatedExpectedArrival, 
                updatedExpectedDeparture: action.updatedExpectedDeparture,
                updatedStatus: action.updatedStatus
            });
        }
        return record;
    });

    return state.merge({
        visitorRecords: newRecordsCollection
    });
1 голос
/ 13 мая 2019

Обычно вы используете map в вашем массиве vistorRecords и передаете идентификатор и поля для обновления в действии, например, это будет выглядеть так:

case ON_VISITOR_RECORD_UPDATED:
     console.log(JSON.stringify(state.get("visitorRecords")));
     const updatedRecords = state.visitorRecords.map(record => {
         if (record.id === action.bookingBeingUpdated) {
             return new Map({
                 ...record,
                 expectedArrival: action.updatedExpectedArrival
                 // other fields...
             });
         }
         return record;
     });
return state.merge({
    state,
    fromJS({visitorRecords: updatedRecords})
});
0 голосов
/ 13 мая 2019
Please don't use state.merge you can use 
```return {
       ...state,
       visitorRecords: [...state.visitorRecords,action.visitorRecords]

}```
Please send Id from action after and compare this id in ON_VISITOR_RECORD_UPDATED type like
```visitorRecords: {
       ...state.visitorRecords,
       data: state.visitorRecords.data.map((items) => {
            if (items.id=== action.id) {
               return { ...items, name: "updated name" };
             }
              return items;
            })
     }```
0 голосов
/ 13 мая 2019

Рекомендуется на самом деле map() существовать и возвращать новое, включающее обновленные значения элементов, которые вы желаете.

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

dispatch({
   type: "ON_VISITOR_RECORD_UPDATED"
   payload: newRecordData
})

Теперь в вашем редукторе:

export default (state = initialState, action) => {
  switch (action.type) {
    case ON_VISITOR_RECORDS_FETCHED:
      return state.merge({
        visitorRecords: fromJS(action.visitorRecords),
      });
    case ON_RETURN_APPROVED:
      return state.merge({
        approvedBookingId: action.approvedBookingId,
      });
    case ON_VISITOR_RECORD_UPDATED:
      return {
      ...state,
      visitorRecords: state.visitorRecords.map((record) => {
          if(record.id == action.payload.id){
             return{
                ...record,
                ...action.payload
             }
          }
      })
      }
    default:
      return state;
  }
};

Это гарантирует, что у вас есть совершенно новое значение состояния для вашего редуктора

0 голосов
/ 13 мая 2019

Вы можете обновить свою запись примерно так:

case ON_VISITOR_RECORD_UPDATED:
  return {
      ...state, 
      visitorRecords: state.visitorRecords.map(record => {
        if(record.id.toString===action.bookingBeingUpdated.toString()){
          return {
            ...record, 
            updatedExpectedArrival: action.updatedExpectedArrival, 
            updatedExpectedDeparture: action.updatedExpectedDeparture, 
            updatedStatus: action.updatedStatus
          }
        } else {
          return record
        }
      })
    }
...