我正在尝试更新reducer中的状态,我知道我不应该改变对象或嵌套对象,所以我使用map
表示数组或对象传播对象。但似乎我无法真正改变深度嵌套的价值。
除了我无法改变状态的事实,我真的不喜欢代码看起来如何,特别是我需要做的只是改变一个属性的循环数。我觉得有一种更好,更易读,更高效的方法。
这是州:
const items = [{
name: 'item 1',
id: 'item1',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag2',
name: 'tag 2'
}]
}, {
name: 'item 2',
id: 'item2',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag4',
name: 'tag 4'
}]
}];
这是我要派遣的行动:
const action = {
type: 'CHANGE_TAG_NAME',
payload: {
itemId: 'item2',
tagId: 'tag4',
newTagName: 'tag 44444'
}
};
这是减速器:
const itemsReducer = (state = [], action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const itemIndex = state.findIndex(item => item.id === action.payload.itemId);
const tagIndex = state[itemIndex].tags.findIndex(t => t.id === action.payload.tagId);
const nextTag = {
...state[itemIndex].tags[tagIndex],
name: action.payload.newTagName
};
const nextTags = [
...state[itemIndex].tags.slice(0, tagIndex),
nextTag,
...state[itemIndex].tags.slice(tagIndex + 1, ),
];
const nextItem = {
...state[itemIndex],
tags: nextTags
};
const nextState = [
...state.slice(0, itemIndex),
nextItem,
...state.slice(itemIndex + 1)
];
}
default:
return state;
}
};
答案 0 :(得分:2)
您忘记了关键字return
//.....
const nextState = [
...state.slice(0, itemIndex),
nextItem,
...state.slice(itemIndex + 1)
];
// HERE RETURN
return newState;
}
default:
return state;
答案 1 :(得分:2)
你的减速机应该工作得很好,你只是忘了在你的案件块中返回nextState
。
至于较少的迭代,我建议这种模式:
映射项目,如果当前项目的ID与有效负载中的itemId
不同,则按原样返回。
如果项目的ID相同,则返回一个新对象,然后映射到标签上,执行与您对项目相同的条件。
如果标记的id与有效负载中的tagId
相同,则返回原样,如果相同,则返回一个新对象。
这是一个正在运行的例子:
const items = [{
name: 'item 1',
id: 'item1',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag2',
name: 'tag 2'
}]
}, {
name: 'item 2',
id: 'item2',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag4',
name: 'tag 4'
}]
}];
const action = {
type: 'CHANGE_TAG_NAME',
payload: {
itemId: 'item2',
tagId: 'tag4',
newTagName: 'tag 44444'
}
};
const itemsReducer = (state = [], action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const {
payload: {
itemId,
tagId,
newTagName
}
} = action;
const nextState = state.map(item => {
if (item.id !== itemId) return item;
return {
...item,
tags: item.tags.map(tag => {
if (tag.id !== tagId) return tag;
return {
...tag,
name: newTagName
}
})
}
});
return nextState;
}
default:
return state;
}
};
console.log(itemsReducer(items, action));

至于更易读的代码,我建议使用更多的减速器
我使用的规则的拇指是为每个实体创建一个减速器:
itemsReducer,
itemReducer,
tagsReducer,
tagReducer。
这样每个reducer都会负责自己的数据。
这是一个正在运行的例子:
const items = [{
name: 'item 1',
id: 'item1',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag2',
name: 'tag 2'
}]
}, {
name: 'item 2',
id: 'item2',
tags: [{
id: 'tag1',
name: 'tag 1'
}, {
id: 'tag4',
name: 'tag 4'
}]
}];
const action = {
type: 'CHANGE_TAG_NAME',
payload: {
itemId: 'item2',
tagId: 'tag4',
newTagName: 'tag 44444'
}
};
const tagReducer = (state = {}, action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const {
payload: {
newTagName
}
} = action;
const nextState = {
...state,
name: newTagName
}
return nextState;
}
default:
return state;
}
}
const tagsReducer = (state = [], action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const {
payload: {
tagId
}
} = action;
const nextState = state.map(tag => {
if (tag.id !== tagId) return tag;
return tagReducer(tag, action);
});
return nextState;
}
default:
return state;
}
}
const itemReducer = (state = {}, action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const nextState = {
...state,
tags: tagsReducer(state.tags, action)
}
return nextState;
}
default:
return state;
}
}
const itemsReducer = (state = [], action) => {
switch (action.type) {
case 'CHANGE_TAG_NAME':
{
const {
payload: {
itemId
}
} = action;
const nextState = state.map(item => {
if (item.id !== itemId) return item;
return itemReducer(item, action)
});
return nextState;
}
default:
return state;
}
};
console.log(itemsReducer(items, action));

此模式通常称为reducer composition,您不必将它们全部包含在根reducer中,只需将它们用作外部纯函数,它将计算其他reducer的相关状态部分。