在 React 应用程序中更新此 Redux 存储状态的正确方法是什么

What is the proper way of updating this Redux store state in React app

我有一个使用 Redux 进行状态管理的 React 应用程序。 store的初始结构如下:

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"
   }
]

我想在我的 reducer 中做的是通过它的 id 更新一个特定的记录。我有来自我的操作的编辑字段的 ID 和值,但我不知道如何按照更新的最佳实践来处理它们。

这是我的减速器的样子:

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

我正在阅读 this 文章,但我不太明白更新是如何发生的。另外,那里的容器结构不同。

编辑:visitorRecords 中的元素类型不是匿名对象而是 Map

您可以像这样更新您的记录:

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

最佳做法是 map() 现有状态和 return 一个新状态,其中包含您想要的 item-values 更新。

假设您分派一个动作和一个负载,其中包含您要使用的 ID 和新值:

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

这确保您拥有一个全新的 state-value 用于您的减速器

您通常会在您的 vistorRecords 数组上使用 map,并在操作中传递要更新的 ID 和字段,因此例如它看起来像这样:

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

以下是使用 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
    });
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;
            })
     }```