从 React 中的状态数组中删除项目
Removing item from state array in React
我在 React 中有一个名为 Spec
的功能组件,它有一个具有以下界面的块列表。 Spec
维护用户添加、编辑或删除的块列表。
问题:删除操作未按预期运行。
- 如果只有一个块,那么它什么都不做,函数中的第一个
console.log()
returns 是一个空数组(长度应该是1),第二个console.log()
returns长度为1的数组(应该是空的)
- 如果数组中有两个以上的块,无论我删除哪个
index
,数组最后的(n-1)
个元素都被删除
谁能看出我做错了什么?
//types.d.ts
interface Block extends Array {
type: string,
block: StoryBlock | MarkdownBlock
}
interface StoryBlock {
title: string,
description: string,
visibility: boolean,
status: string,
}
interface MarkdownBlock {
title: string,
description: string,
visibility: boolean,
}
const Spec: React.FC<OptSpecProps> = (props) => {
const [blocks, setBlocks] = useState<Block[]>([]);
...
const addBlock = (type: string) => {
let blockSeed;
switch (type) {
case "story":
blockSeed = emptyStoryData;
break;
case "markdown":
blockSeed = emptyMarkdownText
break;
default:
blockSeed = emptyMarkdownText
break;
}
const newBlockArray = blocks.concat({type: type, block: blockSeed})
setBlocks([...newBlockArray]);
};
const removeBlock = (index: number) => {
console.log(blocks) //This logs an empty array
const newBlockArray = blocks.splice(index, 1);
console.log(newBlockArray) // this logs the correct array
setBlocks([...newBlockArray])
}
const updateBlock = (index: number, type: string, block: StoryBlock | MarkdownBlock) => {
let newBlockArray: Block[] = blocks;
newBlockArray[index] = {type: type, block: block};
newBlockArray.forEach((block_itr: Block, i: number) => {
if (i === index) {
block_itr.block = block
block_itr.block.visibility = true
} else {
block_itr.block.visibility = false
}
})
setBlocks([...newBlockArray]);
};
这里是 link 到 simplified component sandbox,但从评论中我们已经确定了问题
您正在将新块设置为 splice()
方法的结果,尽管该方法会原地改变数组并且 returns 已删除 元素。
相反,您应该克隆数组然后拼接它
const removeBlock = (index: number) => {
const newBlockArray = [...blocks];
newBlockArray.splice(index, 1);
setBlocks(newBlockArray)
}
P.S。请注意,上面执行的是数组的浅表复制,但在这种情况下应该不是问题。
我在 React 中有一个名为 Spec
的功能组件,它有一个具有以下界面的块列表。 Spec
维护用户添加、编辑或删除的块列表。
问题:删除操作未按预期运行。
- 如果只有一个块,那么它什么都不做,函数中的第一个
console.log()
returns 是一个空数组(长度应该是1),第二个console.log()
returns长度为1的数组(应该是空的) - 如果数组中有两个以上的块,无论我删除哪个
index
,数组最后的(n-1)
个元素都被删除
谁能看出我做错了什么?
//types.d.ts
interface Block extends Array {
type: string,
block: StoryBlock | MarkdownBlock
}
interface StoryBlock {
title: string,
description: string,
visibility: boolean,
status: string,
}
interface MarkdownBlock {
title: string,
description: string,
visibility: boolean,
}
const Spec: React.FC<OptSpecProps> = (props) => {
const [blocks, setBlocks] = useState<Block[]>([]);
...
const addBlock = (type: string) => {
let blockSeed;
switch (type) {
case "story":
blockSeed = emptyStoryData;
break;
case "markdown":
blockSeed = emptyMarkdownText
break;
default:
blockSeed = emptyMarkdownText
break;
}
const newBlockArray = blocks.concat({type: type, block: blockSeed})
setBlocks([...newBlockArray]);
};
const removeBlock = (index: number) => {
console.log(blocks) //This logs an empty array
const newBlockArray = blocks.splice(index, 1);
console.log(newBlockArray) // this logs the correct array
setBlocks([...newBlockArray])
}
const updateBlock = (index: number, type: string, block: StoryBlock | MarkdownBlock) => {
let newBlockArray: Block[] = blocks;
newBlockArray[index] = {type: type, block: block};
newBlockArray.forEach((block_itr: Block, i: number) => {
if (i === index) {
block_itr.block = block
block_itr.block.visibility = true
} else {
block_itr.block.visibility = false
}
})
setBlocks([...newBlockArray]);
};
这里是 link 到 simplified component sandbox,但从评论中我们已经确定了问题
您正在将新块设置为 splice()
方法的结果,尽管该方法会原地改变数组并且 returns 已删除 元素。
相反,您应该克隆数组然后拼接它
const removeBlock = (index: number) => {
const newBlockArray = [...blocks];
newBlockArray.splice(index, 1);
setBlocks(newBlockArray)
}
P.S。请注意,上面执行的是数组的浅表复制,但在这种情况下应该不是问题。