gpt4 book ai didi

reactjs - 即使不改变对象和数组,也无法更改 reducer 中的嵌套对象

转载 作者:行者123 更新时间:2023-12-03 14:08:54 25 4
gpt4 key购买 nike

我正在尝试更新 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'
}
};

这是 reducer :

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;
}
};

最佳答案

你的 reducer 应该工作得很好,你只是忘记在你的 case block 中返回 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));

为了使代码更具可读性,我建议使用更多的reducer。
我使用的一个规则是为每个实体创建一个 reducer :
itemsReducer,
itemReducer,
标签 reducer ,
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 组合,您不必将它们全部包含在根 reducer 中,只需将它们用作外部纯函数来计算其他 reducer 的状态的相关部分。

关于reactjs - 即使不改变对象和数组,也无法更改 reducer 中的嵌套对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47611672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com