React&Redux,更新状态,错误:在调度之间检测到状态突变

时间:2019-08-20 17:46:59

标签: javascript reactjs redux react-redux

我遇到的问题是我的保存数据往返。

错误:browser.js:34未捕获(已承诺)不变违反:在调度之间的路径profile.user.alias中检测到状态突变。

我是React&Redux的新手,但我认为本书已经完成了所有工作。我想念什么?

  1. 我在组件中创建一个本地状态,并分配从mapStateToProps返回的对象。

  2. 我在文本字段的onChange上设置状态。

  3. 在单击保存时,我将调用mapDispatchToProps中定义的操作传递给其本地状态。注意,由于我使用REST Api在服务器上保存日期,因此映射操作是Thunk函数。

  4. 服务器保存数据,并返回带有填充新ID等的相同对象。

  5. 在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。

我已确保在“集合”中使用的对象,动作,归约器等完全相同的链与有效的“获取”动作中的相同。

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中的代码段

// 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);

请帮助。我没有选择了。

2 个答案:

答案 0 :(得分:0)

您可能正在变异由react-redux传递的道具。

在使用props.profileprops.user的地方检查所有代码,以下代码可能是罪魁祸首

props.profile.friends.splice(0, 1);

答案 1 :(得分:0)

当您对收到的道具进行突变并使用该突变的道具调度动作时,会发生状态突变错误。因此,要进行此类分派,请在接收道具时将其复制到本地状态,然后对该状态进行更改,然后使用该状态分派动作。

如果收到的道具是嵌套对象,请使用
进行深度复制 JSON.parse(JSON.stringify());

因此,在您的代码中,在进行分派之前,将道具复制到一个状态并使用该状态进行分派。