You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React点击删除按钮时如何准确删除列表对应目标项

问题描述

我正在开发用户语言编辑功能,支持用户新增、移除已有语言,语言数据以数组形式存储。控制台打印的编辑组件内language数组值为:
language in edit component: ["English", "German"]

当前功能异常表现:

  • 点击列表第一项(German)的删除按钮可正常删除该项
  • 点击第二项(English)的删除按钮时,实际删除的仍是German,English会保留
  • 新增第三项语言后,点击第三项的删除按钮,依然只会删除列表第一项

问题效果截图

原始问题代码

文件路径:Languages.js

export default function Languages({ email, setEmail }) {

  const deleteLanguage = (index) => {
    const list = [...language];
    list.splice(index, 1);
    setLanguage(list);
  };

  return (
    <div>
      {language.map((o, i) => {
        return (
          <tr key={"item-" + i}>
            <td>
              <div>
                <input
                  type="text"
                  value={language}
              </div>
            </td>
            <td >
              <button
                type="button"
                onClick={deleteLanguage}
              >
                Delete
              </button>
            </td>
          </tr>
        );
      })}
  );
}
问题原因

三个错误直接导致删项逻辑完全失效:

  1. 删除按钮的onClick事件根本没传当前遍历项的索引,点任何按钮调用deleteLanguage时,入参index都是undefined,Array.splice()接收到非数值类型的起始位置时,默认从下标0开始删,所以永远删第一个元素
  2. 列表渲染拿数组下标当key属性,增删数组元素后下标会变,React做DOM对比时会复用错误的节点,最后界面显示和内部状态完全对不上
  3. 输入框的value绑了整个language数组,不是当前遍历的单条语言数据,就算删项逻辑对了,输入框内容也会显示乱码

另外代码还有两个隐性问题:组件接收的props是email和setEmail,但代码里直接用了没声明的language和setLanguage变量,运行时直接会报变量未定义的错;同时tr标签不能直接当div的子元素,必须套在table标签里,不然HTML结构非法。

修复后可运行代码
import { useState } from 'react';

export default function Languages() {
  // 补全language状态声明,如果语言数据需要绑定到email对象,对应调整setter逻辑即可
  const [language, setLanguage] = useState(["English", "German"]);

  const deleteLanguage = (index) => {
    const list = [...language];
    list.splice(index, 1);
    setLanguage(list);
  };

  return (
    <div>
      <table>
        {language.map((item, i) => {
          return (
            // 不要用数组下标作为动态列表的key,这里组合内容和索引生成临时唯一key,有业务唯一id时优先用业务id
            <tr key={`lang-${item}-${i}`}>
              <td>
                <div>
                  <input
                    type="text"
                    // 绑定当前遍历的单条语言值
                    value={item}
                    onChange={(e) => {
                      const newList = [...language];
                      newList[i] = e.target.value;
                      setLanguage(newList);
                    }}
                  />
                </div>
              </td>
              <td>
                <button
                  type="button"
                  // 点击时传入当前项的索引
                  onClick={() => deleteLanguage(i)}
                >
                  Delete
                </button>
              </td>
            </tr>
          );
        })}
      </table>
    </div>
  );
}
修复要点
  • 给删除按钮的点击事件传入当前遍历项的索引,确保splice操作命中正确的数组位置
  • 动态列表不要用数组下标作为key,避免React DOM复用出错
  • 表单控件要绑定当前遍历的单条数据,不要直接绑定整个数组
  • 保证组件内使用的变量都有对应声明,HTML标签嵌套符合规范

内容的提问来源于stack exchange,提问作者van123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:36:17