【问题标题】:Removing item from state array in React从 React 中的状态数组中删除项目
【发布时间】:2020-12-30 20:04:54
【问题描述】:

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

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

  1. 如果只有一个块,那么它什么也不做,函数中的第一个console.log()返回一个空数组(它应该是长度为1),第二个console.log()返回一个长度为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]);
  };

这是一个指向simplified component sandbox 的链接,但从我们发现问题的 cmets 来看

【问题讨论】:

  • 仅供参考 - 调用 setBlocks 不会立即更新状态。在组件重新渲染之前它不会更新。
  • 尝试使用useCallback钩子定义removeBlock函数
  • @ToddSkelton 我正在使用useEffect 在每个渲染上检查blocks,但它没有更新。所以我认为这意味着它甚至没有更新状态?我仍然不清楚为什么blocks 首先在函数中登录到undefined,即使我可以在视图中看到它
  • 我可以赌你在渲染块时使用index作为key的甜甜圈。对于可变列表,您不能这样做,每个块都需要自己的唯一标识符作为key prop
  • 你也是直接用 splice 改变状态,这是错误的。你应该先从你的数组中复制,而不是直接处理

标签: arrays reactjs use-state


【解决方案1】:

您正在将新块设置为splice() 方法的结果,但是,该方法会在原地改变数组并返回删除的 元素。 相反,你应该克隆数组然后拼接它

const removeBlock = (index: number) => {
  const newBlockArray = [...blocks];
  newBlockArray.splice(index, 1);
  setBlocks(newBlockArray)
}

附:请注意,上面执行了数组的浅拷贝,但在这种情况下应该不是问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 2021-03-10
    • 2020-06-23
    相关资源
    最近更新 更多