admin管理员组文章数量:1398813
I know this question has been asked before, but in almost all of them talk about the OP mutating the state directly, which I've tried to avoid using techniques like the spread operator (in both objects and arrays) but in spite of that I'm getting the following error:
Uncaught Error: A state mutation was detected between dispatches, in the path `courses.0`. This may cause incorrect behavior. (.html#never-mutate-reducer-arguments)
at invariant (eval at <anonymous> (bundle.js:922), <anonymous>:40:15)
at eval (eval at <anonymous> (bundle.js:3825), <anonymous>:50:36)
at eval (eval at <anonymous> (bundle.js:3846), <anonymous>:14:16)
at dispatch (eval at <anonymous> (bundle.js:3853), <anonymous>:37:18)
at eval (eval at <anonymous> (bundle.js:1151), <anonymous>:63:5)
at eval (eval at <anonymous> (bundle.js:3846), <anonymous>:11:18)
at Object.eval [as saveCourse] (eval at <anonymous> (bundle.js:3860), <anonymous>:4:12)
at Object.ManageCoursePage._this.saveCourse [as onSave] (eval at <anonymous> (bundle.js:2080), <anonymous>:134:27)
at CourseForm._this.onHandleSave (eval at <anonymous> (bundle.js:2052), <anonymous>:93:19)
at Object.ReactErrorUtils.invokeGuardedCallback (eval at <anonymous> (bundle.js:1301), <anonymous>:69:16)
I read the article that the error points to, and as it suggests I checked if I was manually mutating the state in my reducer and I can't see where that could be happening:
const courseReducer = (state = initialState.courses, action) => {
switch (action.type) {
case types.LOAD_COURSE_SUCCESS:
return action.courses;
case types.CREATE_COURSE_SUCCESS:
//This action throw the error
debugger;
return [
...state,
Object.assign({}, action.course)
];
case types.UPDATE_COURSE_SUCCESS:
//This action throw the error
debugger;
return [
...state.filter(course => course.id !== action.course.id),
Object.assign({}, action.course)
];
case types.DELETE_COURSE_SUCCESS:
return [...state.filter(course => course.id !== action.courseId)];
default:
return state;
}
};
Here's a sandbox with part of the application that can be used to replicate the error, which weirdly only happens from times to times when I create a new course or try to edit an existing one (actions CREATE_COURSE_SUCCESS
and UPDATE_COURSE_SUCCESS
respectively in my courseReducer
)
I'd really appreciate if anyone could help me figure out where could be lying the source of this error.
I know this question has been asked before, but in almost all of them talk about the OP mutating the state directly, which I've tried to avoid using techniques like the spread operator (in both objects and arrays) but in spite of that I'm getting the following error:
Uncaught Error: A state mutation was detected between dispatches, in the path `courses.0`. This may cause incorrect behavior. (http://redux.js/docs/Troubleshooting.html#never-mutate-reducer-arguments)
at invariant (eval at <anonymous> (bundle.js:922), <anonymous>:40:15)
at eval (eval at <anonymous> (bundle.js:3825), <anonymous>:50:36)
at eval (eval at <anonymous> (bundle.js:3846), <anonymous>:14:16)
at dispatch (eval at <anonymous> (bundle.js:3853), <anonymous>:37:18)
at eval (eval at <anonymous> (bundle.js:1151), <anonymous>:63:5)
at eval (eval at <anonymous> (bundle.js:3846), <anonymous>:11:18)
at Object.eval [as saveCourse] (eval at <anonymous> (bundle.js:3860), <anonymous>:4:12)
at Object.ManageCoursePage._this.saveCourse [as onSave] (eval at <anonymous> (bundle.js:2080), <anonymous>:134:27)
at CourseForm._this.onHandleSave (eval at <anonymous> (bundle.js:2052), <anonymous>:93:19)
at Object.ReactErrorUtils.invokeGuardedCallback (eval at <anonymous> (bundle.js:1301), <anonymous>:69:16)
I read the article that the error points to, and as it suggests I checked if I was manually mutating the state in my reducer and I can't see where that could be happening:
const courseReducer = (state = initialState.courses, action) => {
switch (action.type) {
case types.LOAD_COURSE_SUCCESS:
return action.courses;
case types.CREATE_COURSE_SUCCESS:
//This action throw the error
debugger;
return [
...state,
Object.assign({}, action.course)
];
case types.UPDATE_COURSE_SUCCESS:
//This action throw the error
debugger;
return [
...state.filter(course => course.id !== action.course.id),
Object.assign({}, action.course)
];
case types.DELETE_COURSE_SUCCESS:
return [...state.filter(course => course.id !== action.courseId)];
default:
return state;
}
};
Here's a sandbox with part of the application that can be used to replicate the error, which weirdly only happens from times to times when I create a new course or try to edit an existing one (actions CREATE_COURSE_SUCCESS
and UPDATE_COURSE_SUCCESS
respectively in my courseReducer
)
I'd really appreciate if anyone could help me figure out where could be lying the source of this error.
Share Improve this question edited Dec 17, 2017 at 5:23 Andrew Li 58k14 gold badges134 silver badges148 bronze badges asked Jun 3, 2017 at 17:58 eddyeddy 4,41317 gold badges67 silver badges99 bronze badges 2-
Can we see how you use your state, via
mapStateToProps
? – Andrew Li Commented Jun 3, 2017 at 18:06 -
Sure! It is a bit messy, but I already added under an Edit. Btw you can found the same code in the sandbox I included in my question, just look for the file
ponents/course/ManageCoursePage.js
– eddy Commented Jun 3, 2017 at 18:13
1 Answer
Reset to default 7The problem is that you are mutating state, inside CoursesPage.js
, in mapStateToProps
:
let courses = state.courses.sort((c1, c2) =>
c1.title.localeCompare(c2.title, 'en', { sensitivity: 'base' }),
);
Array#sort
is an in place operation, so it mutates the source array by sorting the source array in place. That means, sort
is mutating state.courses
, thus causing the error. Instead, make a copy of state.courses
before you sort it:
[...state.courses]
The above uses spread syntax to spread the elements into a new array essentially cloning it. This is the same as Array#slice
. Then you can sort it like so:
let courses = [...state.courses].sort((c1, c2) =>
c1.title.localeCompare(c2.title, 'en', { sensitivity: 'base' }),
);
This will not mutate the original state.courses
and will not throw an error.
Note: There are also some places where you are mutating this.state
directly, such as in line 32 of ManageCoursePage.js
where you do:
this.state.errors = {}
Only ever mutate the this.state
object in the constructor of the ponent. Use setState
instead.
版权声明:本文标题:javascript - A state mutation was detected between dispatches but I haven't mutated state - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744091181a2589453.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论