使用useState从数组中删除项目

3

我试图从错误中移除一个项目,但它并没有像预期那样工作。

我正在使用状态:

  const [actions, setActions] = useState([
    {
      action: "",
      key: ""
    }
  ]);

我有一个按钮用于添加功能:

    <IconButton
      icon="add"
      bgColor="white"
      iconColor="darkGray"
      onClick={() =>
        setActions([
          ...actions,
          {
            action: "",
            key: ""
          }
        ])
      }
    />

每行都有一个删除按钮,我正在尝试使用行索引来删除 actions 数组中的项:

      <IconButton
        disabled={actions.length === 1}
        icon="dash"
        iconColor="red"
        onClick={() => {
          console.log(index);
          setActions(actions => {
            return [...actions.splice(index, 1)];
          });
        }}
      />

https://codesandbox.io/s/actions-selector-n9xb4


1
splice会改变原始数组并返回删除的元素。我认为你没有使用正确的数组方法... - Brian Thompson
1
这个回答解决了你的问题吗?使用redux删除一个项目的正确方式是什么? - XCS
2个回答

11

试试使用filter。它不会修改现有的数组,并且可以像这样使用:

setActions(prevActions => (
  // Filter out the item with the matching index
  prevActions.filter((value, i) => i !== index)
));

过滤器难道不比切片慢吗?因为它必须遍历所有元素并进行比较。 - XCS
1
"!== "会更好。应该鼓励最佳实践给 OP,对吧? ;) - Andrew
1
我认为你对性能是正确的,但我不认为 slice 返回他们想要的内容。它返回“提取”的项目。 - Brian Thompson
1
@XCS 你需要在两个方向上进行切片。它将是 [...actions.slice(0, i), ...actions.slice(i + 1)]。哪个更快取决于编译器。到了某个程度,这就是无谓的争论。只需编写更清晰易懂的代码即可。 - Andrew
1
如果你真的想要达到微观优化的那个层次,你可以很容易地在一个名为 filterActions 的函数中声明它,并将其提供给过滤器。但我真的不认为性能的提升可以弥补代码清晰度的损失。 - Brian Thompson
显示剩余12条评论

1
  <IconButton
    disabled={actions.length === 1}
    icon="dash"
    iconColor="red"
    onClick={() => {
      setActions(actions.filter((item, i) => i !== index));
    }}
  />

我在您的Codesandbox中测试了它,它可以工作


它无法正确跟踪被删除的内容。因此,如果我在关键输入中放入a、b、c,我删除了b,那么c也会被删除。 - Batman
它可以跟踪,检查:https://codesandbox.io/s/actions-selector-wgxdp,可能你只需要将ActionDropdown与actions状态连接起来,就可以了。 - Luis Montoya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接