React & Redux,更新状态,错误:在调度之间检测到状态突变
Posted
技术标签:
【中文标题】React & Redux,更新状态,错误:在调度之间检测到状态突变【英文标题】:React & Redux, Update state, Error: A state mutation was detected between dispatches 【发布时间】:2019-12-25 23:46:03 【问题描述】:我遇到的问题是我的保存数据往返。
错误:browser.js:34 Uncaught (in promise) Invariant Violation:在路径 profile.user.alias
中检测到调度之间的状态突变。
我是 React 和 Redux 的新手,但我认为我已经完成了一切。我错过了什么?
我在组件中创建一个本地状态并分配从 mapStateToProps 返回的对象。
我在文本字段的 onChange 上设置状态。
在保存单击时,我调用 mapDispatchToProps 中定义的操作,将本地状态传递给它。注意,映射的动作是一个 Thunk 函数,因为我使用 REST Api 在服务器上保存日期。
服务器保存数据并返回相同的对象,并填写新的 Id 等。
在 fetch.then() 中,我调度一个动作,传递从服务器返回的对象。
错误在调度线上。
export function setUserProfile (profile)
return function(dispatch)
return setProfile(profile) <-- the API call
.then(p =>
dispatch(handleSetProfileSuccess(p));
)
.catch(error =>
throw error;
);
;
从昨天开始我就一直在努力解决这个错误。我已经尝试了所有我发现的技巧,包括从 Redux-Starter-Kit 更改为 createReducer。
我已确保我在“set”中使用的对象、动作、reducer 等完全相同的链与在“get”中有效的动作相同。
export function handleSetProfileSuccess (profile)
return type: types.SET_USER_PROFILE_SUCCESS, profile ;
export function setUserProfile (profile)
return function(dispatch)
return setProfile(profile) <--- the api call with fetch
.then(p =>
dispatch(handleSetProfileSuccess(p));
)
.catch(error =>
throw error;
);
;
// the action is never dispatched on save since the error is on the dispatch line above.
// the Redux way
export default function profileReducer(state = , action)
switch (action.type)
case types.GET_USER_PROFILE_SUCCESS:
return ...state, ...action.profile ;
case types.SET_USER_PROFILE_SUCCESS:
return ...state, ...action.profile ;
default:
return state;
// the redux-starter-kit way
const profileReducer=createReducer(,
GET_USER_PROFILE_SUCCESS: (state, action) => state=action.profile,
SET_USER_PROFILE_SUCCESS: (state,action) => state=action.profile
);
整个往返行程有效。新数据保存在服务器上,服务器返回的对象是正确的。 .then() 调用中的参数“p”确实包含正确的数据。但它在调用
时崩溃dispatch(handleSetProfileSuccess(p));
编辑:这是 profile.js 中的代码 sn-ps
// profile.js
state = ...this.props.profile ;
// on save click handler
setData = e =>
e.preventDefault();
// validate stuff here
this.props.setProfile(this.state).then(() =>
this.setState(prevState => (
...prevState,
...this.props.profile
));
);
;
export function mapStateToProps(state)
return
user: state.user,
profile: state.profile
;
const mapDispatchToProps =
getProfile: profileActions.getUserProfile,
setProfile: profileActions.setUserProfile
;
export default connect(
mapStateToProps,
mapDispatchToProps
)(Profile);
请帮忙。我别无选择。
【问题讨论】:
不确定这是否是问题所在,但这不需要返回:return setProfile
。
是否会为类型 SET_USER_PROFILE_SUCCESS 调用减速器?
没有。由于错误在调度调用中,因此永远不会到达减速器。
您能否显示您可能正在访问该状态路径的任何其他位置?您是在 mapState
函数中还是在组件文件中阅读它? (另外,我要指出,这正是 RSK 在默认情况下添加“突变检测”中间件的原因 - 以捕获这些类型的错误。)
setProfile 函数在所有 API 的模块中定义。它返回一个承诺。
【参考方案1】:
很可能你正在改变 react-redux 传递的 prop。
检查你使用props.profile
或props.user
的所有代码,像下面这样的代码可能是罪魁祸首
props.profile.friends.splice(0, 1);
【讨论】:
【参考方案2】:当您对接收到的道具进行突变并使用该突变道具分派操作时,会发生状态突变错误。因此,要进行此类调度,请在接收 props 时将其复制到本地 state,对 state 进行更改并使用 state 调度 action。
如果收到的 props 是嵌套对象,请使用 JSON.parse(JSON.stringify());
因此,在您的代码中,在进行分派之前,将道具复制到一个状态并使用该状态进行分派。
【讨论】:
以上是关于React & Redux,更新状态,错误:在调度之间检测到状态突变的主要内容,如果未能解决你的问题,请参考以下文章
REACT + REDUX:在 redux 状态更改时 mapStateToProps 更新状态,但视图未按照新状态呈现