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

React动态表格渲染key属性添加位置及编辑异常修复

问题修复方案

你的代码存在3个核心问题,分别导致key属性警告、编辑功能失效、空输入时表格不显示,逐一修复即可:

  • key警告原因:map遍历生成的直接子元素是<Fragment>,你之前把key绑定在Fragment内部的EditableRow/ReadOnlyRow组件上,React无法识别列表项的唯一标识;且List.js中未导入Fragment,本身会触发语法错误。
  • 编辑失效原因:你将编辑后的数据保存在contacts state中,但过滤逻辑始终使用导入的原始静态data做筛选渲染,state更新后页面不会读取修改后的值,编辑操作无法生效。
  • 空输入不显示内容原因:搜索词为空时过滤逻辑返回空字符串(falsy值),所有数据都会被过滤,表格无内容。

修复步骤

1. 修复App.js

补上缺失的useState导入,修复后完整代码:

import { useState } from "react";
import TextField from "@mui/material/TextField";
import List from "./Components/List";
import "./App.css";

function App() {
  const [inputText, setInputText] = useState("");
  let inputHandler = (e) => {
    // 输入内容转小写
    var lowerCase = e.target.value.toLowerCase();
    setInputText(lowerCase);
  };

  return (
    <div className="main">
      <h1>Search</h1>
      <div className="search">
        <TextField
          id="outlined-basic"
          onChange={inputHandler}
          variant="outlined"
          fullWidth
          label="Search"
        />
      </div>
      <List input={inputText} />
    </div>
  );
}

export default App;

2. 修复List.js

  • 补上Fragment、useState的导入
  • 将key绑定到map返回的最外层Fragment上
  • 过滤逻辑改用contacts state作为数据源,替换原始静态data
  • 修正空搜索词的过滤逻辑,无输入时返回全部数据
    修复后完整代码:
import { useState, Fragment } from "react";
import data from "./ListData.json"
import ReadOnlyRow from "./ReadOnlyRow.js"
import EditableRow from "./EditableRow.js"

function List(props) {
    const [contacts, setContacts]=useState(data);
    const [editContactId, setEditContactId] = useState(null);
    const [editFormData, setEditFormData] = useState({
        CustomerLogonId: "",
        FirstName: "",
        LastName: "",
        Address: "",
        City: "",
        Zip: "",
      });

      const handleFormChange = (event) => {
        const fieldName = event.target.getAttribute("name");
        const fieldValue = event.target.value;

        const newFormData = {...editFormData};
        newFormData[fieldName] = fieldValue;

        setEditFormData(newFormData);
    };

    const handleFormSubmit = (event) => {
        event.preventDefault();
        const editedContact = {
            id : editContactId, 
            CustomerLogonId: editFormData.CustomerLogonId,
            FirstName: editFormData.FirstName,
            LastName: editFormData.LastName,
            Address: editFormData.Address,
            City: editFormData.City,
            Zip: editFormData.Zip
        }
        const newContacts = [...contacts];

        const index = contacts.findIndex((item) => item.id === editContactId)
        newContacts[index] = editedContact;
        setContacts(newContacts);
        setEditContactId(null);
    }
      const handleEditClick = (event, item) => {
        event.preventDefault();
        setEditContactId(item.id);
        const formValues = {
            CustomerLogonId: item.CustomerLogonId,
            FirstName: item.FirstName,
            LastName: item.LastName,
            Address: item.Address,
            City: item.City,
            Zip: item.Zip
        }
        setEditFormData(formValues);
    }

    const handleCancelClick = () => {
        setEditContactId(null);
      };

    // 改用contacts state作为过滤数据源,修正空输入逻辑
    const filteredData = contacts.filter((el) => {
        // 无输入时返回所有数据
        if (props.input === '') {
            return true;
        }
        // 匹配输入的邮箱字段
        else {
            return el.CustomerLogonId.toLowerCase().includes(props.input)
        }
    })
    return (
        <div className='app-container'>
            <form onSubmit={handleFormSubmit}>
            <table>
                <thead>
                    <tr>
                        <th>CustomerLogonId</th>
                        <th>FirstName</th> 
                        <th>LastName</th> 
                        <th>Address</th> 
                        <th>City</th>
                        <th>Zip</th>
                        <th>Actions</th>
                    </tr>
                </thead>

            <tbody>
                {filteredData.map((item) => (
                // key绑定到map遍历的最外层直接子元素上
                <Fragment key={item.id}>
                   {editContactId === item.id ? (
                     <EditableRow editFormData={editFormData} handleFormChange={handleFormChange} handleCancelClick={handleCancelClick} />
                   ) : (
                     <ReadOnlyRow item = {item} handleEditClick = {handleEditClick} />
                   ) } 
                </Fragment>
                
    ))}
            </tbody>

            </table>
            </form>
        </div>
    )

                }
export default List

3. ReadOnlyRow.js、EditableRow.js、ListData.json

这三个文件逻辑无问题,不需要修改。

修复后控制台key警告会消失,点击Edit按钮可以正常进入编辑状态,修改后点Save即可保存更新内容,搜索框无输入时会显示全部客户数据,输入关键词时实时过滤匹配结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:21:33