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;
});
我意识到这个错误可能有一百万零一个不同的原因,但我正在努力寻找我的原因。我对 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;
});