【问题标题】:A state mutation was detected between dispatches but I haven't mutated state在调度之间检测到状态突变,但我没有突变状态
【发布时间】:2017-11-04 22:21:43
【问题描述】:

我知道以前有人问过这个问题,但几乎所有人都在谈论 OP 直接改变状态,我试图避免使用像扩展运算符这样的技术(在对象和数组中),但尽管如此其中我收到以下错误:

Uncaught Error: A state mutation was detected between dispatches, in the path `courses.0`. This may cause incorrect behavior. (http://redux.js.org/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)

我阅读了the article that the error points to,正如它所暗示的那样,我检查了我是否在减速器中手动改变了状态,但我看不到可能发生的情况:

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

这里是a sandbox with part of the application,可用于复制错误,奇怪的是,只有在我创建新课程或尝试编辑现有课程时才会不时发生这种错误(操作CREATE_COURSE_SUCCESSUPDATE_COURSE_SUCCESS分别在我的@ 987654333@)

如果有人能帮助我找出这个错误的根源,我将不胜感激。

【问题讨论】:

  • 我们可以通过mapStateToProps查看您如何使用您的状态吗?
  • 当然!这有点乱,但我已经在编辑下添加了。顺便说一句,您可以在我的问题中包含的沙箱中找到相同的代码,只需查找文件 components/course/ManageCoursePage.js

标签: javascript reactjs ecmascript-6 redux react-redux


【解决方案1】:

问题是你正在改变状态,在CoursesPage.js,在mapStateToProps

let courses = state.courses.sort((c1, c2) =>
  c1.title.localeCompare(c2.title, 'en', { sensitivity: 'base' }),
);

Array#sort 是一个就地操作,因此它通过对源数组进行就地排序来改变源数组。这意味着,sort 正在变异 state.courses,从而导致错误。相反,在排序之前复制state.courses

[...state.courses]

上面使用spread syntax 将元素传播到一个新数组中,基本上是克隆它。这与Array#slice 相同。然后你可以这样排序:

let courses = [...state.courses].sort((c1, c2) =>
  c1.title.localeCompare(c2.title, 'en', { sensitivity: 'base' }),
);

这不会改变原来的state.courses,也不会抛出错误。


注意:还有一些地方是你直接修改this.state,比如ManageCoursePage.js的第32行你做的:

this.state.errors = {}

只在组件的构造函数中改变this.state 对象。请改用setState

【讨论】:

  • 我的错!你介意告诉我你是如何找到我手动改变状态的地方的吗?错误堆栈中没有对CoursesPage.js 的引用。
  • 由于错误消息,我怀疑它与mapStateToProps 有关,我在那里寻找它。该消息说“在调度之间”,因此它与connecting 或减速器有关。由于减速机很好,我去看了你的connects。此外,有时使用 Ctrl+F 搜索 state = 会有所帮助。
  • 好的。我只是想也许有一个包:)
猜你喜欢
  • 2019-10-13
  • 2016-12-08
  • 2019-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多