React Final Form:Field Array初始值传递及表单值格式处理
解决React Final Form Field Array结合react-select、react-sortable-hoc的两个问题
问题1:移除fruitName嵌套,直接存储水果对象
原代码中SortableItem组件里的Field使用了${name}.fruittName(存在拼写错误,应为fruitName)作为字段名,导致每个数组元素都嵌套在fruitName下。要实现直接存储水果对象的结构,需做以下修改:
- 将
Field的name直接设为name(对应数组元素本身) - 手动适配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
相关产品推荐
相关产品推荐

