【发布时间】:2020-12-30 20:04:54
【问题描述】:
我在 React 中有一个名为 Spec 的函数组件,它有一个具有以下接口的块列表。 Spec 维护用户添加、编辑或删除的块列表。
问题:删除操作未按预期工作。
- 如果只有一个块,那么它什么也不做,函数中的第一个
console.log()返回一个空数组(它应该是长度为1),第二个console.log()返回一个长度为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]);
};
这是一个指向simplified component sandbox 的链接,但从我们发现问题的 cmets 来看
【问题讨论】:
-
仅供参考 - 调用
setBlocks不会立即更新状态。在组件重新渲染之前它不会更新。 -
尝试使用
useCallback钩子定义removeBlock函数 -
@ToddSkelton 我正在使用
useEffect在每个渲染上检查blocks,但它没有更新。所以我认为这意味着它甚至没有更新状态?我仍然不清楚为什么blocks首先在函数中登录到undefined,即使我可以在视图中看到它 -
我可以赌你在渲染块时使用
index作为key的甜甜圈。对于可变列表,您不能这样做,每个块都需要自己的唯一标识符作为keyprop -
你也是直接用 splice 改变状态,这是错误的。你应该先从你的数组中复制,而不是直接处理