从 React 中的状态数组中删除项目

Removing item from state array in React

我在 React 中有一个名为 Spec 的功能组件,它有一个具有以下界面的块列表。 Spec 维护用户添加、编辑或删除的块列表。

问题:删除操作未按预期运行。

  1. 如果只有一个块,那么它什么都不做,函数中的第一个console.log() returns 是一个空数组(长度应该是1),第二个console.log() returns长度为1的数组(应该是空的)
  2. 如果数组中有两个以上的块,无论我删除哪个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。请注意,上面执行的是数组的浅表复制,但在这种情况下应该不是问题。