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

React中动态添加的多组输入框如何实现独立更新?

问题描述

我有一个React表单,初始包含若干默认的姓名(name)和地址(address)值。当用户点击Add按钮时,会新增一组可输入姓名和地址的输入框,输入内容将存储在additionConfigs状态中。

当前实现中,使用config.id来更新新增的姓名和地址,但存在问题:若用户为同一基础项添加多组输入框,修改其中一组时,同id的其他组也会同步更新。请问如何实现各组输入框的独立更新?是否需要为每组输入框添加唯一标识?

现有代码
import "./styles.css";
import { useState, useEffect } from "react";

export default function App() {
  const [value, setValue] = useState([]);
  const [additionConfigs, setAdditionConfigs] = useState([]);
  useEffect(() => {
    setTimeout(() => {
      setValue([
        {
          id: 1,
          baseName: "XXX",
          config: {
            name: "Kenny",
            address: "New york"
          }
        },
        {
          id: 2,
          baseName: "YYY",
          config: {
            name: "Ben",
            address: "Boston"
          }
        },
        {
          id: 3,
          baseName: "ZZZ",
          config: {
            name: "Mary",
            address: "Los Angeles"
          }
        }
      ]);
    }, 1000);
  }, []);
  const onAddBaseConfig = (item) => {
    setAdditionConfigs((preValue) => [
      ...preValue,
      {
        id: item.id,
        config: {
          name: "",
          address: ""
        }
      }
    ]);
  };
  console.log(additionConfigs);
  const onChangeName = (e, id) => {
    setAdditionConfigs((preValue) => {
      const newValue = preValue.map((v) => {
        if (v.id === id) {
          return {
            ...v,
            config: {
              ...v.config,
              name: e.target.value
            }
          };
        }
        return v;
      });
      return newValue;
    });
  };
  const onChangeAddress = (e, id) => {
    setAdditionConfigs((preValue) => {
      const newValue = preValue.map((v) => {
        if (v.id === id) {
          return {
            ...v,
            config: {
              ...v.config,
              address: e.target.value
            }
          };
        }
        return v;
      });
      return newValue;
    });
  };
  return (
    <>
      {value.length > 0 &&
        value.map((v, index) => (
          <div className="item" key={index}>
            <div className="item">
              {v.config.name} &nbsp;
              {v.config.address} &nbsp;
              {additionConfigs.length > 0 &&
                additionConfigs
                  .filter((config) => config.id === v.id)
                  .map((config) => (
                    <div>
                      <label>name</label>
                      <input
                        value={config.config.name}
                        onChange={(e) => onChangeName(e, config.id)}
                      />
                      <label>address</label>
                      <input
                        value={config.config.address}
                        onChange={(e) => onChangeAddress(e, config.id)}
                      />
                    </div>
                  ))}
            </div>
            <button onClick={() => onAddBaseConfig(v)}>Add</button>
          </div>
        ))}
    </>
  );
}
解决方案

问题根源在于你用基础项的id作为新增输入框的唯一标识,当同一基础项添加多组输入框时,它们的id完全相同,导致修改时所有同id的输入框都会被更新。必须给每组新增的输入框添加独立的唯一标识,才能实现单独更新。

具体修改步骤:

  1. 新增输入框时,给每个条目生成唯一标识(可以用时间戳+随机数的组合,生产环境建议用成熟的uuid库)
  2. 更新输入框内容时,用这个唯一标识来定位要修改的条目,而不是基础项的id

修改后的代码示例:

import "./styles.css";
import { useState, useEffect } from "react";

// 生成简单的唯一id,生产环境推荐使用uuid库
const generateUniqueId = () => {
  return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
};

export default function App() {
  const [value, setValue] = useState([]);
  const [additionConfigs, setAdditionConfigs] = useState([]);

  useEffect(() => {
    setTimeout(() => {
      setValue([
        { id: 1, baseName: "XXX", config: { name: "Kenny", address: "New york" } },
        { id: 2, baseName: "YYY", config: { name: "Ben", address: "Boston" } },
        { id: 3, baseName: "ZZZ", config: { name: "Mary", address: "Los Angeles" } }
      ]);
    }, 1000);
  }, []);

  const onAddBaseConfig = (item) => {
    setAdditionConfigs((preValue) => [
      ...preValue,
      {
        // 新增唯一标识,确保每组输入框独立
        uniqueId: generateUniqueId(),
        // 保留基础项id用于关联对应基础条目
        baseId: item.id,
        config: { name: "", address: "" }
      }
    ]);
  };

  const onChangeName = (e, uniqueId) => {
    setAdditionConfigs((preValue) =>
      preValue.map((v) =>
        v.uniqueId === uniqueId
          ? { ...v, config: { ...v.config, name: e.target.value } }
          : v
      )
    );
  };

  const onChangeAddress = (e, uniqueId) => {
    setAdditionConfigs((preValue) =>
      preValue.map((v) =>
        v.uniqueId === uniqueId
          ? { ...v, config: { ...v.config, address: e.target.value } }
          : v
      )
    );
  };

  return (
    <>
      {value.length > 0 &&
        value.map((v) => (
          <div className="item" key={v.id}>
            <div className="item">
              {v.config.name} &nbsp;
              {v.config.address} &nbsp;
              {additionConfigs
                .filter((config) => config.baseId === v.id)
                .map((config) => (
                  <div key={config.uniqueId}>
                    <label>name</label>
                    <input
                      value={config.config.name}
                      onChange={(e) => onChangeName(e, config.uniqueId)}
                    />
                    <label>address</label>
                    <input
                      value={config.config.address}
                      onChange={(e) => onChangeAddress(e, config.uniqueId)}
                    />
                  </div>
                ))}
            </div>
            <button onClick={() => onAddBaseConfig(v)}>Add</button>
          </div>
        ))}
    </>
  );
}

关键改动说明:

  • 新增generateUniqueId函数生成唯一标识,确保每组输入框拥有独立身份
  • 修改additionConfigs结构:用baseId关联对应基础项,用uniqueId作为自身唯一标识
  • 更新输入框的修改逻辑,通过uniqueId精准定位要修改的条目
  • 渲染新增输入框时,用uniqueId作为React列表项的key,符合React的性能优化要求

这样修改后,同一基础项的多组输入框就能独立更新,不会再出现同步修改的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:45:25