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

如何在React.js中基于JSON数组渲染3个及以上动态表单

Hey there! Let's walk through how to render those dynamic grouped forms in React using your field configuration. First off, I noticed a tiny syntax issue in your fields array—you used curly braces instead of square brackets, and a couple of missing commas in the select_one objects. I'll fix those in the example below to make everything work smoothly.

Step 1: Clean Up & Structure Your Field Data

First, let's correct the field configuration to valid JS syntax:

const fields = [
  { id: 1, type: 'group' },
  { id: 2, type: 'text', label: 'Name', group_id: 1 },
  { id: 3, type: 'text', label: 'Address', group_id: 1 },
  { id: 4, type: 'text', label: 'City', value: 'Lahore', group_id: 1 },
  { id: 5, type: 'text', label: 'State', value: 'Punjab', group_id: 1 },
  { id: 6, type: 'text', label: 'Country', value: 'Pakistan', group_id: 1 },
  { id: 7, type: 'group' },
  { id: 8, type: 'date', label: 'Date of birth', group_id: 7 },
  { id: 9, type: 'email', label: 'Email', group_id: 7 },
  { id: 10, type: 'phone', label: 'Phone', group_id: 7 },
  { id: 11, type: 'color', label: 'Color', value: '#ff9900', group_id: 7 },
  { id: 12, type: 'number', label: 'Age', value: 22, group_id: 7 },
  { id: 13, type: 'number', label: 'Friends', value: 3, group_id: 7 },
  { id: 14, type: 'select_one', label: 'Select One City', value: 'karachi', choices: ['lahore', 'karachi', 'multan', 'faisalabad', 'pishawar', 'queta', 'islamabad'], group_id: 7 },
  { id: 15, type: 'select_one', label: 'Select One Fruit', value: 'peach', choices: ['apple', 'banana', 'mango', 'peach', 'grapes', 'pine', 'strawberry'], group_id: 7 }
];

Step 2: Group Fields by Their group_id

We need to organize fields into their respective groups so we can render each group as a separate form section. Let's write a helper function to do this:

const groupFields = () => {
  const groups = {};
  // First, collect all group objects
  fields.forEach(field => {
    if (field.type === 'group') {
      groups[field.id] = { ...field, fields: [] };
    }
  });
  // Then assign each field to its group
  fields.forEach(field => {
    if (field.type !== 'group' && field.group_id) {
      groups[field.group_id].fields.push(field);
    }
  });
  // Convert the groups object to an array for easy rendering
  return Object.values(groups);
};

Step 3: Create a Reusable Field Component

Let's build a component that renders the correct input type based on the field's type prop. This keeps our code DRY (Don't Repeat Yourself):

const FormField = ({ field, value, onChange }) => {
  const handleChange = (e) => {
    onChange(field.id, e.target.value);
  };

  switch (field.type) {
    case 'text':
    case 'email':
    case 'phone':
      return (
        <div className="form-field">
          <label>{field.label}</label>
          <input
            type={field.type}
            value={value}
            onChange={handleChange}
          />
        </div>
      );
    case 'date':
      return (
        <div className="form-field">
          <label>{field.label}</label>
          <input
            type="date"
            value={value}
            onChange={handleChange}
          />
        </div>
      );
    case 'color':
      return (
        <div className="form-field">
          <label>{field.label}</label>
          <input
            type="color"
            value={value}
            onChange={handleChange}
          />
        </div>
      );
    case 'number':
      return (
        <div className="form-field">
          <label>{field.label}</label>
          <input
            type="number"
            value={value}
            onChange={handleChange}
          />
        </div>
      );
    case 'select_one':
      return (
        <div className="form-field">
          <label>{field.label}</label>
          <select value={value} onChange={handleChange}>
            {field.choices.map(choice => (
              <option key={choice} value={choice}>
                {choice.charAt(0).toUpperCase() + choice.slice(1)}
              </option>
            ))}
          </select>
        </div>
      );
    default:
      return null;
  }
};

Step 4: Build the Main Form Component

Now we'll put it all together: manage form state, group the fields, and render each group with its fields.

import React, { useState, useEffect } from 'react';

const DynamicGroupedForm = () => {
  // Initialize form state with default values from fields
  const [formState, setFormState] = useState({});

  useEffect(() => {
    const initialState = {};
    fields.forEach(field => {
      initialState[field.id] = field.value ?? '';
    });
    setFormState(initialState);
  }, []);

  const handleFieldChange = (fieldId, newValue) => {
    setFormState(prev => ({
      ...prev,
      [fieldId]: newValue
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    // Do something with the form data, like submit to an API
    console.log('Form submitted:', formState);
  };

  const groupedFields = groupFields();

  return (
    <form onSubmit={handleSubmit} className="grouped-form">
      {groupedFields.map(group => (
        <div key={group.id} className="form-group">
          <h3>Group {group.id}</h3>
          {group.fields.map(field => (
            <FormField
              key={field.id}
              field={field}
              value={formState[field.id]}
              onChange={handleFieldChange}
            />
          ))}
        </div>
      ))}
      <button type="submit">Submit Form</button>
    </form>
  );
};

export default DynamicGroupedForm;

Step 5: Add Some Basic Styling (Optional)

To make the forms look clean, add a bit of CSS:

.grouped-form {
  max-width: 800px;
  margin: 2rem auto;
  padding: 0 1rem;
}

.form-group {
  border: 1px solid #eee;
  padding: 1.5rem;
  margin-bottom: 1.5rem;
  border-radius: 8px;
}

.form-field {
  margin-bottom: 1rem;
}

.form-field label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

.form-field input,
.form-field select {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  padding: 0.75rem 1.5rem;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background: #0056b3;
}

Quick Breakdown:

  • Data Grouping: The groupFields function organizes each field into its assigned group, making it easy to render each group as a distinct section.
  • Reusable Field Component: FormField handles all input types, so you don't have to repeat code for each field type.
  • State Management: We initialize the form state with the default values from your fields array, and update it whenever a field changes.
  • Scalability: If you add more groups or field types later, you just need to update the FormField switch case and add the new field to the fields array—no major rewrites needed.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:32:58