【问题标题】:Dynamically Delete Elements动态删除元素
【发布时间】:2022-01-01 05:45:24
【问题描述】:

我在删除元素时遇到问题。它不会删除特定元素,而是仅删除最后一个新创建的元素。我不确定我要去哪里错了。我引用了this tutorial,这表明我有点想做。 (我是 React 新手)

import React,{useState, useRef} from "react";


const Body = () => {
    const [list, setList] = useState([]);

    const AddInput = () => {
        setList([...list, {placeholder:"Class Name"}]);
    };

    const DeleteInput = (index) => {
        const l = [...list];
        l.splice(index,1);
        setList(l);
    };

    const InputChangeHandler = (event, index) => {
        const l = [...list];
        (l[index]).value = event.target.value;
        setList(l);
    };

    return (
        <div>
            <button onClick={AddInput}>Add</button>
            {list.map((item, key)=> 
                <div key={key}>
                    <input type={"text"} id={key} placeholder={item.placeholder} onChange={e=>InputChangeHandler(e, key)}/>
                    <button id={key} onClick={() => DeleteInput(key)}>Delete</button>
                </div>
            )}
        </div>
    );
}

export default Body;

元素(输入字段+按钮):

删除上次创建的:

【问题讨论】:

  • 我建议用filter 方法和元素的id来处理

标签: javascript reactjs react-hooks


【解决方案1】:

我认为主要问题是您设置为 react doc 所说的项目的关键:

当您没有用于渲染项目的稳定 ID 时,您可以使用项目索引作为键作为最后的手段:

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

我们不建议使用索引作为键,如果项目的顺序可能 改变。这可能会对性能产生负面影响,并可能导致问题 与组件状态。查看 Robin Pokorny 的文章 深入解释使用指数作为指标的负面影响 钥匙。如果您选择不为列表项分配显式键,则 React 将默认使用索引作为键。

正如Article 所说:

当索引用作键时,重新排序列表或从列表中添加和删除项目可能会导致组件状态出现问题。如果键是索引,则重新排序项目会更改它。因此,组件状态可能会混淆,并可能将旧密钥用于不同的组件实例。

有哪些例外情况可以安全地使用索引作为键?

-如果你的列表是静态的并且不会改变。

-列表永远不会被重新排序。

-列表不会被过滤(从列表中添加/删除项目)。

-列表中的项目没有ID。

如果您使用一些计数器或 id 生成器在您的项目中设置一个可靠的密钥,您的问题就会解决。

类似这样的:

export default function App() {
  const [list, setList] = useState([]);
  const id = useRef({ counter: 0 });

  const AddInput = () => {
    console.log(id);
    setList([...list, { placeholder: "Class Name", id: id.current.counter++ }]);
  };

  const DeleteInput = (id) => {
    setList(list.filter((item, i) => item.id !== id));
  };

  const InputChangeHandler = (event, index) => {
    const l = [...list];
    l[index].value = event.target.value;
    setList(l);
  };

  return (
    <div>
      <button onClick={AddInput}>Add</button>
      {list.map((item, key) => (
        <div key={item.id}>
          <input
            type={"text"}
            id={key}
            placeholder={item.placeholder}
            onChange={(e) => InputChangeHandler(e, key)}
          />
          <button id={item.id} onClick={() => DeleteInput(item.id)}>
            Delete
          </button>
        </div>
      ))}
    </div>
  );
}
【解决方案2】:

使用过滤器。

const DeleteInput = (index) => {
  const l = list.filter((_, i) => i !== index);
  setList(l);
};

【讨论】:

    【解决方案3】:

    将 id 传递给您的 DeleteInput 函数,删除时只需过滤带有 id 的项目列表

    const DeleteInput = (id) => {const filterItemList = list.filter((item) => item.id!== id);setList(filterItemList ); };
    

    【讨论】:

      猜你喜欢
      • 2011-07-20
      • 2019-12-29
      • 2016-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 2013-10-02
      • 2022-01-25
      相关资源
      最近更新 更多