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

React Final Form:Field Array初始值传递及表单值格式处理

解决React Final Form Field Array结合react-select、react-sortable-hoc的两个问题

问题1:移除fruitName嵌套,直接存储水果对象

原代码中SortableItem组件里的Field使用了${name}.fruittName(存在拼写错误,应为fruitName)作为字段名,导致每个数组元素都嵌套在fruitName下。要实现直接存储水果对象的结构,需做以下修改:

  1. 将Field的name直接设为name(对应数组元素本身)
  2. 手动适配react-select的value和onChange,因为react-select返回的是完整对象,需要直接传递给Final Form的输入处理函数

修改后的SortableItem组件:

const SortableItem = SortableElement(({ name, fields, value }) => (
  <li>
    <DragHandle />
    <Field name={name}>
      {({ input: { value: fieldValue, onChange } }) => (
        <Select
          options={options}
          placeholder="Select Fruit"
          value={fieldValue}
          onChange={(selectedOption) => onChange(selectedOption)}
        />
      )}
    </Field>
    <span onClick={() => fields.remove(value)} style={{ cursor: "pointer" }}>
      Remove
    </span>
  </li>
));

问题2:设置Field Array的初始值

给Form组件添加initialValues属性,传入已选水果列表即可,格式与期望的表单值结构一致:

<Form
  onSubmit={onSubmit}
  mutators={{
    ...arrayMutators,
  }}
  initialValues={{
    company: "",
    fruits: [
      { id: 3, value: "vanilla", label: "Vanilla" },
      { id: 1, value: "chocolate", label: "Chocolate" }
    ]
  }}
  render={/* ... 原有渲染逻辑 ... */}
/>

完整修改后的代码

import React from "react";
import Styles from "./Styles";
import { Form, Field } from "react-final-form";
import arrayMutators from "final-form-arrays";
import { FieldArray } from "react-final-form-arrays";
import {
  SortableContainer,
  SortableElement,
  SortableHandle,
} from "react-sortable-hoc";
import Select from "react-select";

const options = [
  { id: 1, value: "chocolate", label: "Chocolate" },
  { id:2, value: "strawberry", label: "Strawberry" },
  { id:3, value: "vanilla", label: "Vanilla" },
];
const DragHandle = SortableHandle(() => (
  <span style={{ cursor: "move" }}>Drag</span>
));

const SortableItem = SortableElement(({ name, fields, value }) => (
  <li>
    <DragHandle />
    <Field name={name}>
      {({ input: { value: fieldValue, onChange } }) => (
        <Select
          options={options}
          placeholder="Select Fruit"
          value={fieldValue}
          onChange={(selectedOption) => onChange(selectedOption)}
        />
      )}
    </Field>
    <span onClick={() => fields.remove(value)} style={{ cursor: "pointer" }}>
      Remove
    </span>
  </li>
));

const SortableList = SortableContainer(({ items }) => {
  return (
    <ul>
      {items.map((name, index) => (
        <SortableItem
          key={`item-${index}`}
          index={index}
          value={index}
          name={name}
          fields={items}
        />
      ))}
    </ul>
  );
});

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const onSubmit = async (values) => {
  await sleep(300);
  window.alert(JSON.stringify(values, 0, 2));
};

const sortEnd =
  (move) =>
  ({ oldIndex, newIndex }) => {
    move(oldIndex, newIndex);
  };
const Home = () => {
  return (
    <div>
      <Styles>
        <h1>React Final Form - Array Fields</h1>
        <Form
          onSubmit={onSubmit}
          mutators={{
            ...arrayMutators,
          }}
          initialValues={{
            company: "",
            fruits: [
              { id: 3, value: "vanilla", label: "Vanilla" },
              { id: 1, value: "chocolate", label: "Chocolate" }
            ]
          }}
          render={({ handleSubmit, form: { mutators: { push, pop } }, pristine, reset, submitting, values }) => {
            return (
              <form onSubmit={handleSubmit}>
                <div>
                  <label>Company</label>
                  <Field name="company" component="input" />
                </div>

                <div className="buttons">
                  <button
                    type="button"
                    onClick={() => push("fruits", undefined)}
                  >
                    Add Fruit
                  </button>
                  <button type="button" onClick={() => pop("fruits")}>
                    Remove Last Fruit
                  </button>
                </div>
                <FieldArray name="fruits">
                  {({ fields }) => (
                    <SortableList
                      useDragHandle={true}
                      items={fields}
                      onSortEnd={sortEnd(fields.move)}
                    />
                  )}
                </FieldArray>
                <div className="buttons">
                  <button type="submit" disabled={submitting || pristine}>
                    Submit
                  </button>
                  <button
                    type="button"
                    onClick={reset}
                    disabled={submitting || pristine}
                  >
                    Reset
                  </button>
                </div>
                <pre>{JSON.stringify(values, 0, 2)}</pre>
              </form>
            );
          }}
        />
      </Styles>
    </div>
  );
};

export default Home;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:40:25