Можно предположить следующие переменные:
click = true
categories = [
{title: "all", onClick: false},
{title: "video", onClick: false},
{title: "gif", onClick: false},
{title: "website", onClick: false}
]
finalCategories = [
{title: "all", onClick: true},
{title: "video", onClick: true},
{title: "gif", onClick: true},
{title: "website", onClick: true}
]
У меня здесь есть набор редукционных действий:
import * as actionTypes from './actionTypes';
import {beginAjaxCall, ajaxCallError} from './ajaxStatusActions';
import * as Utils from './utils/dashboardActionsUtils';
export function updateCategoriesSuccess(categories) {
return {type: actionTypes.UPDATE_CATEGORIES_SUCCESS, categories};
}
export function categoryAllClick(categories, click) {
return function(dispatch) {
dispatch(beginAjaxCall());
const finalCategories = Utils.updateMenuOnAll(categories, click);
dispatch(updateCategoriesSuccess(finalCategories));
};
}
Где:
export function updateMenuOnAll(menu, click) {
const finalMenu = Object.assign([], menu);
if (click) {
finalMenu.map(item => item.onClick = true);
} else {
finalMenu.map(item => item.onClick = false);
}
return finalMenu;
}
Однако,когда я звоню categoryAllClick(categories, click)
, actionTypes.UPDATE_CATEGORIES_SUCCESS
не попадает в мой редуктор:
import * as actionTypes from '../actions/actionTypes';
import initialState from './initialState';
export default function dashboardReducer(state = initialState.dashboard, action) {
switch(action.type) {
case actionTypes.UPDATE_CATEGORIES_SUCCESS:
return Object.assign({}, state, {categories: action.categories});
default:
return state;
}
}
Я предполагаю, что это потому, что при попытке выполнить это действие я получаю сообщение об ошибке:
2 Uncaught Error: 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)
Что-то я делаю неправильно в экспортированной функции updateMenuOnAll, чтобы вызвать эту мутацию состояния?Я думал, что использование Object.assign()
позволит избежать этой проблемы.Спасибо!
РЕДАКТИРОВАТЬ
Следующим компонентом реакции является тот, который вызывает categoryAllClick
, при нажатии на соответствующий div:
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as dashboardActions from '../../../../../actions/dashboardActions';
class CheckboxItem extends React.Component {
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
const {menu, title, type, categoryAllClick, tagAllClick, actions} = this.props;
if (type === "categories") {
if (title === "all") {
actions.categoryAllClick(menu, !categoryAllClick);
} else {
actions.updateCategories(title, menu);
}
} else if (type === "tags") {
if (title === "all") {
actions.tagAllClick(menu, !tagAllClick);
} else {
actions.updateTags(title, menu);
}
}
}
render() {
return (
<div className="div-common-menu-item" onClick={this.handleClick}>
// Child componenets here
</div>
);
}
}
CheckboxItem.propTypes = {
menu: PropTypes.array.isRequired,
title: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
categories: PropTypes.array.isRequired,
tags: PropTypes.array.isRequired,
categoryAllClick: PropTypes.bool.isRequired,
tagAllClick: PropTypes.bool.isRequired,
actions: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
categories: state.dashboard.categories,
tags: state.dashboard.tags,
categoryAllClick: state.dashboard.categoryAllClick,
tagAllClick: state.dashboard.tagAllClick
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(dashboardActions, dispatch)
};
}
const connectedStateAndProps = connect(mapStateToProps, mapDispatchToProps);
export default connectedStateAndProps(CheckboxItem);