Redux:在调度中检测到状态突变

Redux: A state mutation was detected inside a dispatch

我意识到这个错误可能有一百万零一个不同的原因,但我正在努力寻找我的原因。我对 Reducer 中的 Redux 和状态处理比较陌生,并且从网上的一些示例中学到了下面在 Reducer 中调用的代码示例:

const updateTripsWhereVenueDeleted = (state, action) => {
  debugger;
  const deletedVenueId = action.venue.Id;
  const originalTrips = [...state];

  const newTrips = originalTrips.map((trip) => {
    if (trip.VenueId === deletedVenueId) {
      trip.VenueId = 0;
      trip.VenuePegId = 0;
    }
    return trip;
  });
  debugger;
  return [...newTrips];
};

我有 state 这是一个 Trips 数组:

并且 Action 包含一条 'Venue' 记录。 基本上,正在传递的场地已被删除,我想更新所有引用已删除场地的旅行的相关字段。

当我 运行 Reducer 中的上述代码时,事情似乎朝着正确的方向发展,直到浏览器崩溃并出现以下错误:

Unhandled Rejection (Invariant Violation): A state mutation was detected inside a dispatch, in the path: trips.0.VenueId. Take a look at the reducer(s) handling the action {"type":"UPDATE_TRIPS_VENUE_DELETED","venue": {.... the object}

UPDATE_TRIPS_VENUE_DELETED就是上面调用我方法的action.type

在状态或其他情况下处理(展开)数组是否存在明显的误用。我觉得这应该是一件容易的事,但到目前为止我没有尝试过任何正确的事情。

展开对象或数组([...state] 此处)不会破坏嵌套引用。因此,您通过不在 map -- trip.VenueId = 0;.

中复制嵌套对象来改变状态

这导致另一个观察结果,map returns 一个新数组,因此这否定了完全使用 originalTrips 的需要。做 state.map() 一样安全。最后的spread [...newTrips] 也绝对没有必要。

要修复您的变更,请创建要更新的对象的克隆:

const updateTripsWhereVenueDeleted = (state, action) => {

  const deletedVenueId = action.venue.Id;

  const newTrips = state.map((trip) => {
    if (trip.VenueId === deletedVenueId) {
      // Copy other trip values into NEW object and return it
      return { ...trip, VenueId: 0, VenuePegId: 0 };
    }
    // If not matched above, just return the old trip
    return trip;
  });

  return newTrips;
};

展开运算符...只做浅拷贝。如果数组是嵌套的或multi-dimensional,它将不起作用。

我们有很多方法可以做到这一点,下面是其中的一些

1] 使用 JSON

的深度复制
  const originalTrips = JSON.parse(JSON.stringify(state));;

2]

const newTrips = originalTrips.map((trip) => {
  
    if (newTrip.VenueId === deletedVenueId) {
      let newTrip = Object.assign({},trip);
      newTrip.VenueId = 0;
      newTrip.VenuePegId = 0;
      return newTrip;
    }
    return trip;
  });