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

React动态增减输入框遇event.target未定义问题及优化咨询

问题原因、修复与优化方案

一、handleFocusOut参数错误的原因

你在输入框的onBlur回调里调用handleFocusOut(index)时,只传递了index,没有传递事件对象event。这导致handleFocusOut函数的第一个参数event实际接收到的是index的值(比如0),自然不存在event.target属性,从而触发报错。

二、快速修复方法

修改输入框的onBlur回调,把事件对象传递进去:

<SpecificationValue
  placeholder="Key"
  onChange={handleSpecKeyChange}
  name="key"
  onBlur={(e) => handleFocusOut(e, index)} // 补充传递事件对象e
/>
<SpecificationValue
  placeholder="Value"
  onChange={handleSpecValueChange}
  name="value"
  onBlur={(e) => handleFocusOut(e, index)} // 同样修改此处
/>

但这只是解决了当前报错,你的代码还存在核心问题:用单个specificationKeys和specificationValues状态存储所有输入框的值,新增输入框后,输入内容会覆盖之前的值,无法正确维护多组key-value的对应关系。

三、更优的实现方案

直接用specifications数组状态维护每一组输入项,每一项是包含key和value的对象,精准对应每一组输入框,同时简化逻辑:

修改后的App.js代码

import React, { useState } from "react";
import {
  SpecificationFormContainer,
  SpecificationFormCard,
  SpecificationFormTitle,
  SpecificationInputRow,
  SpecificationValue,
  AddMoreButton,
  RemoveButton
} from "./Elements";
import "./styles.css";

export default function App() {
  // 用数组存储每一组规格,初始为空
  const [specifications, setSpecifications] = useState([]);

  // 新增一组空的key-value项
  const handleAdd = () => {
    setSpecifications(prev => [...prev, { key: "", value: "" }]);
  };

  // 删除最后一组项
  const handleRemove = () => {
    setSpecifications(prev => prev.slice(0, -1));
  };

  // 更新指定索引的key或value
  const handleInputChange = (index, field, value) => {
    setSpecifications(prev => {
      const newSpecs = [...prev];
      newSpecs[index][field] = value;
      return newSpecs;
    });
  };

  // 提交时转换为需要的POST数据格式
  const handleSubmit = (e) => {
    e.preventDefault();
    const payload = specifications
      .filter(item => item.key.trim() && item.value.trim()) // 过滤空项
      .map(item => ({ item: 1, ...item }));
    console.log("POST请求数据:", payload);
    // 此处可发起POST请求
  };

  return (
    <SpecificationFormContainer>
      <SpecificationFormCard>
        <SpecificationFormTitle>Add Specifications</SpecificationFormTitle>
        <form onSubmit={handleSubmit}>
          {specifications.map((spec, index) => (
            <SpecificationInputRow key={index}>
              <SpecificationValue
                placeholder="Key"
                value={spec.key}
                onChange={(e) => handleInputChange(index, "key", e.target.value)}
              />
              <SpecificationValue
                placeholder="Value"
                value={spec.value}
                onChange={(e) => handleInputChange(index, "value", e.target.value)}
              />
            </SpecificationInputRow>
          ))}
          <div>
            <AddMoreButton type="button" onClick={handleAdd}>
              Add
            </AddMoreButton>
            {specifications.length > 0 && (
              <RemoveButton type="button" onClick={handleRemove}>
                Remove
              </RemoveButton>
            )}
            <button type="submit">提交</button>
          </div>
        </form>
      </SpecificationFormCard>
    </SpecificationFormContainer>
  );
}

方案优势

  1. 状态管理更合理:用数组存储每一组输入项,避免单个状态覆盖问题,key-value一一对应。
  2. 逻辑简化:无需额外维护numberOfSpecFields,数组长度就是输入框组数,增删操作直接操作数组。
  3. 数据格式直接可用:提交时过滤空项,给每个对象添加item:1即可得到目标POST结构。
  4. 受控组件实现:所有输入框为受控组件,状态与输入值保持同步,避免非受控组件的潜在问题。

四、扩展说明

  • 若需支持删除任意一组,可给每个删除按钮绑定对应索引,修改handleRemove为接收索引参数后删除对应项。
  • 可在输入框onBlur回调中添加空值校验,确保key和value不为空。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:45:38