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

React中如何将动态新增的ProductOrder组件转为对象数组?

解决方案

核心思路

用数组状态管理所有ProductOrder的条目数据,给每个条目分配唯一ID,让子组件通过回调更新父组件中对应ID的条目,以此精准区分每个组件的输入并生成对应对象。

具体实现

1. 父组件状态与逻辑

在表单所在的父组件中,统一管理所有表单数据,包括基础字段和动态新增的items条目:

import { useState } from 'react';

function OrderForm() {
  // 初始化表单状态,包含基础字段和初始商品条目
  const [formData, setFormData] = useState({
    providerId: '',
    isPayed: false,
    orderArrive: '',
    items: [{ id: Date.now(), productName: '', quantity: '', price: '' }]
  });

  // 点击"+"新增商品条目
  const addProductOrder = () => {
    setFormData(prev => ({
      ...prev,
      items: [...prev.items, { id: Date.now(), productName: '', quantity: '', price: '' }]
    }));
  };

  // 处理商品条目输入变化
  const handleItemChange = (itemId, updatedFields) => {
    setFormData(prev => ({
      ...prev,
      items: prev.items.map(item => 
        item.id === itemId ? { ...item, ...updatedFields } : item
      )
    }));
  };

  // 处理基础表单字段变化(供应商、支付状态、到货日期)
  const handleBasicFieldChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  // 提交表单,直接使用符合后端格式的状态数据
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('提交数据:', formData);
    // 调用后端API:fetch('/api/orders', { method: 'POST', body: JSON.stringify(formData) })
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <div>
          <label>供应商</label>
          <select 
            name="providerId" 
            value={formData.providerId} 
            onChange={handleBasicFieldChange}
          >
            {/* 填充供应商选项 */}
          </select>
        </div>
        <fieldset>
          <legend>订单信息</legend>
          <div>
            <label>到货日期</label>
            <input 
              type="date" 
              name="orderArrive" 
              value={formData.orderArrive} 
              onChange={handleBasicFieldChange}
            />
          </div>
          <div>
            <label>已支付</label>
            <input 
              type="checkbox" 
              name="isPayed" 
              checked={formData.isPayed} 
              onChange={handleBasicFieldChange}
            />
          </div>
        </fieldset>
        {/* 渲染所有商品条目组件 */}
        {formData.items.map(item => (
          <ProductOrder 
            key={item.id}
            itemId={item.id}
            itemData={item}
            onChange={handleItemChange}
          />
        ))}
        <div>
          <span onClick={addProductOrder}>+</span>
        </div>
        <button type="submit">提交订单</button>
      </div>
    </form>
  );
}

2. 改造ProductOrder子组件

子组件不维护自身状态,通过props接收数据和回调,输入变化时通知父组件更新对应条目:

function ProductOrder({ itemId, itemData, onChange }) {
  const handleInputChange = (e) => {
    const { name, value } = e.target;
    onChange(itemId, { [name]: value });
  };

  return (
    <div className="product-order">
      <div>
        <label>商品名称</label>
        <input 
          type="text" 
          name="productName" 
          value={itemData.productName} 
          onChange={handleInputChange}
        />
      </div>
      <div>
        <label>数量</label>
        <input 
          type="number" 
          name="quantity" 
          value={itemData.quantity} 
          onChange={handleInputChange}
        />
      </div>
      <div>
        <label>单价</label>
        <input 
          type="number" 
          name="price" 
          value={itemData.price} 
          onChange={handleInputChange}
        />
      </div>
    </div>
  );
}

关键说明

  • 用Date.now()生成唯一ID(复杂场景可替换为UUID),确保父组件能精准定位要更新的条目。
  • 所有数据集中在父组件状态管理,遵循React单向数据流,避免状态分散导致的混乱。
  • 提交时formData的结构完全匹配后端要求,直接序列化后即可发送请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:45:34