如何更新嵌套数组与useReducer?



我有这些:

export type DataItemChild = {
id: number;
title:string;
checked?: boolean;
};

注意这里可以不定义子项:

export type DataItems = {
id: number;
title:string;
subItems?: Array<DataItemChild>;
checked?: boolean;
};
export const initalState: StateType = {
items: [],
date: new Date(),
};

到目前为止,我已经弄清楚如何更新数组的顶级对象,如:

case ActionKind.Checked:
newArrayChecked = state.items.map((item) => ({
...item,
checked: item.id === payload.id ? true : item.checked,
}));
return {
...state,
items: newArrayChecked,
};

我不知道如何更新子项?我有这个(删节)

export const reducer = (state: StateType, action: Action) => {
const { type, payload } = action;
let newArrayChildCheck: Array<DataItemChild> = []
switch (type) {
case ActionKind.UnCheckedSub:
newArrayChildCheck = state.items.map((item) => ({
...item.subItems?.map((sub, index) => ({
checked:  sub.id === payload.subItems?[index].id ? true: sub.checked
})),
}));
return {
...state,
items.subItems: newArrayChildCheck,
};
default:
return state;
}
};

但是这给了我一个打字错误,说我的newArrayChildCheck不支持undefined。完整的错误:

Type '{[x: number]: {checked: boolean | undefined;};长度呢?:Number |未定义;toString吗?:(1) =>String) |未定义;toLocaleString吗?:(1) =>String) |未定义;流行吗?:(1) =>{检查:布尔值|未定义;} |未定义)|未定义;…29 . more…(Symbol.unscopables) ?:(1) =>{……;}) |未定义;}[]'不是可分配给类型'DataItemChild[]'。键入"{[x: number]:{"Checked: Boolean |未定义;};长度呢?: number |未定义;toString吗?:(1) =>String) |未定义;toLocaleString吗?:(1) =>字符串)|未定义;流行吗?:(1) =

编辑:

在@Kelvin school的回答之后,我意识到我发送的是一个完整的对象,它有它的子项。有效载荷类型为DataItems

我根据@Kelvin schools的建议修改了我的尝试,并做了一点改动:

newArrayChildCheck = state.items.map((item) => ({
...item,
subItems: item.subItems?.map((sub, index) => ({
...sub,
checked: sub.id === payload.subItems[index].id ? true : sub.checked
})),

不是[index]

但是我得到

对象是可能的

似乎你的新对象传播错误了。你的.map((item) => ...)返回一个对象,但在其中你散布一个(潜在的)数组,它只会填充数字(好吧,字符串化版本)键。您可能想要从item(如idtitle)复制原始字段,并将映射的subItems结果分配给subItems字段。您在subItems?.map中创建的对象的Idem。像这样的内容是类型正确的:

newArrayChildCheck = state.items.map((item) => ({
...item,
subItems: item.subItems?.map((sub) => ({
...sub,
checked: sub.id === payload.id ? true : sub.checked
})),
}));

这是如果你想改变你的DataItems数组的版本。如果您真的想返回checked版本修改后的每个DataItemChild,您可以像这样使用flatMap:

newArrayChildCheck = state.items.flatMap((item) => 
item.subItems?.map((sub) => ({
...sub,
checked: sub.id === payload.id ? true : sub.checked
})),
);

最新更新