Reputation: 3880
I am using React and Redux and trying to dispatch an action from a component but am getting the following error:
AJAX CALL Invariant Violation: A state mutation was detected between dispatches, in the path
dashboard.categories.0.onClick
. This may cause incorrect behavior. (http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments)
You can assume the following:
menu = [
{title: "video", onClick: false},
{title: "gif", onClick: false},
{title: "website", onClick: false}
];
title = 'video';
Here is the component function being used:
itemCheck() {
const {menu, title, actions} = this.props;
actions.updateCategoryClick(title, [...menu]);
}
Redux Action:
export function updateCategoryClickSuccess(categories) {
return {type: actionTypes.UPDATE_CATEGORY_CLICK_SUCCESS, categories};
}
export function updateCategoryClick(category, categories) {
return function(dispatch) {
dispatch(beginAjaxCall());
return Utils.updateMenuClick(category, categories)
.then(categories => {dispatch(updateCategoryClickSuccess(categories));})
.catch(error => {dispatch(ajaxCallError(error));});
};
}
And the utility function being used:
export function updateMenuClick(item, menu) {
return new Promise((resolve) => {
const index = menu.findIndex((object => object.title === item));
menu[index].onClick = !menu[index].onClick;
resolve(menu);
});
}
Question:
Why am I being told that a state mutation is happening between dispatches if in fact what I am sending is not the original state (in this case menu
), but am instead sending it a new copy of the state (in this case [...menu]
)? And how do I fix this? Thanks all!
Upvotes: 0
Views: 359
Reputation: 11270
[...menu]
creates a shallow copy, so this.props.menu[index]
and [...menu][index]
are still referencing the same object.
Try replacing menu[index].onClick = !menu[index].onClick
with:
menu[index] = { ...menu[index], onClick: !menu[index].onClick }
Might be better to do this logic in the reducer though.
Also, returning a promise in your updateMenuClick
is a bit pointless since it's not async.
Upvotes: 3