我正在尝试更改我的reducer上的一个对象,正如我在别处读到的那样,Object.assign在对象上创建了一个新副本,但元素是相同的(https://stackoverflow.com/a/37819614/3808307),所以我不断得到
不变违规,在调度内检测到状态突变
尝试时
let newTravelersObject = Object.assign({}, state.travelers);
我想如果我有一个数组,我可以使用map,我也尝试过使用loadhash _.mapValues但是得到了同样的错误。
另一个解决方案是重构我的代码以使用数组而不是对象,但我不认为我应该这样做,我拒绝相信它无法完成
state.travelers object
{
"results": [
{"id" : 34,
"name": "",
"enemies" : [
{"profession": "Dentist", "id": 54},
{"profession": "Police officer", "id": 471}
},
{"id" : 52,
"name": "Alicia",
"enemies" : [
{"profession": "Architect", "id": 61}
},
...
],
"count": 7
}
case types.ADD_ENEMY_SUCCESS:
let newTraverlersObject = Object.assign({}, state.travelers);
let id = _.findIndex(newTraverlersObject.results, ["id", action.enemy.traveler_id]);
newTraverlersObject.results[id].enemies.push({"id": action.enemy.id, "profession": action.enemy.profession});
return Object.assign({}, state, {
travelers: newTravelersObject
});
state为
的类的构造方法class TravelersPage extends React.Component {
constructor(props, context){
super(props, context);
this.state = {
travelers: Object.assign({}, props.travelers),
currentTravelerId: null,
loading: true,
...
};
答案 0 :(得分:2)
您正在改变嵌套对象,例如results[id].enemies.push
请注意,.findIndex
将返回浅拷贝而不是深拷贝。
我建议重新考虑这里的模式,并考虑更简洁和可读的流程。
只需返回一个新对象,但映射到结果数组,并返回不具有相同traveler_id
的旅行者,当您确实发现相关的traveler
返回一个新对象并覆盖enemies
数组,返回一个带有ES2015扩展功能的新数组,最后添加新的敌人对象。
这是一个正在运行的例子:
const newItems = {
"results": [{
"id": 34,
"name": "",
"enemies": [{
"profession": "Dentist",
"id": 54
}, {
"profession": "Police officer",
"id": 471
}]
}, {
"id": 52,
"name": "Alicia",
"enemies": [{
"profession": "Architect",
"id": 61
}],
}]
};
const action = {
type: 'ADD_ENEMY_SUCCESS',
enemy: {
id: 999,
traveler_id: 34,
profession: 'my new proffesion!!!'
}
};
const travelersReducer = (state = {}, action) => {
switch (action.type) {
case 'ADD_ENEMY_SUCCESS':
{
const {
enemy: {
id,
traveler_id,
profession
}
} = action;
const nextState = {
...state,
results: state.results.map(traveler => {
if (traveler.id !== traveler_id) return traveler; // this is not out target, return the object as is
return { // return a new object
...traveler,
enemies: [
...traveler.enemies, { // new enemy
id,
profession,
}
]
}
})
};
return nextState;
}
defualt: return state;
}
}
console.log(travelersReducer(newItems, action));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
我认为你应该添加更多减速器,我的经验法则是为每个实体创建一个减速器(旅行者减速器,旅行者减速器,敌人减速器,敌人减速器......)。
我不久前实际上answered a similar question并且包含了创建更多缩减器的示例。
请注意,我没有使用Object.assign
,而是使用object spread feature作为提案but in stage 3。