如何在React Hook Form中正确处理动态对象数组表单?
React Hook Form + TypeScript + Zod + ShadCN 动态对象数组表单问题
我是React新手,正在使用React Hook Form(RHF)+TypeScript+Zod+ShadCN构建包含路线站点对象数组的动态表单。已成功实现简单文本及字符串数组字段,但在动态对象数组部分陷入困境。
已完成ShadCN Form组件的配置,使用useFieldArray处理字符串数组时一切正常,但处理对象数组时出现问题。在代码的City字段注释中尝试了多种方案:当使用{...form.register(stops.${index}.city)}时,能正确渲染默认值,但提交按钮无响应,验证会抛出undefined或误判错误,而其他字段功能正常。未收到控制台或编译错误,相关代码如下:
import "./styles.css"; import { zodResolver } from "@hookform/resolvers/zod"; import { useFieldArray, useForm } from "react-hook-form"; import * as z from "zod"; import { Button } from "./button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "./form"; import { Input } from "./input"; const stopObj = z.object({ order: z.coerce.number(), zip: z.string(), city: z.string({ required_error: "This field is required." }), state: z .string({ required_error: "This field is required." }) .max(2, "2-letter state abbreviation"), country: z.coerce .string() .max(2, "Two-letter country code (ISO 3166-1 alpha-2)"), }); const formSchema = z.object({ firstName: z.string({ required_error: "This field is required." }), currency: z.enum(["USD", "CAD"]), stops: z .array(stopObj) .min(2, "2 stops minimum required (pickup and dropoff)"), }); export default function App() { const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { firstName: "John", currency: "USD", stops: [ { order: 1, city: "New York", state: "NY", zip: "02116", country: "US" }, { order: 2, city: "Austin", state: "TX", zip: "12345", country: "US" }, ], }, }); async function onSubmit(values: z.infer<typeof formSchema>) { console.log("onSubmit:", values); } const { fields } = useFieldArray({ name: "stops", control: form.control }); return ( <div className="bg-[#305645] w-full justify-center flex"> <div className="w-3/4 bg-white px-5 py-3 my-20 rounded-lg"> <Form {...form}> <div className="text-center font-medium"> <h1 style={{ fontSize: "2rem", marginBottom: "1rem" }}> Complete Form </h1> </div> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> <div className="flex space-x-4 w-full"> <div className="w-1/2"> <FormField control={form.control} name="firstName" render={({ field }) => ( <FormItem> <FormLabel>First Name</FormLabel> <FormControl> <Input placeholder="John" {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> </div> <FormField control={form.control} name="currency" render={({ field }) => ( <FormItem> <FormLabel>Currency</FormLabel> <FormControl> <Input placeholder="USD" {...field} /> </FormControl> <FormDescription>USD or CAD.</FormDescription> <FormMessage /> </FormItem> )} /> </div> {/* FIXME how to correctly render and update each stop object?? */} {fields.map((field, index) => ( <FormField control={form.control} key={field.id} name={`stops.${index}`} render={({ field }) => ( <> <FormItem> <FormLabel>City</FormLabel> <FormDescription /> <FormControl> <Input {...field.value.city} // {...form.register(`stops.${index}.city`)} // defaultValue={field.name} // value={field.value.city} // onChange={(e) => field.onChange(e.target.value)} // onBlur={(e) => field.onBlur(e.target.value)} /> </FormControl> <FormMessage /> </FormItem> <FormItem> <FormLabel>State</FormLabel> <FormDescription /> <FormControl> <Input {...form.register(`stops.${index}.state`)} // defaultValue={field.name} /> </FormControl> <FormMessage /> </FormItem> </> )} /> ))} <Button type="submit" className="bg-orange-500 font-extrabold w-full" > Submit </Button> </form> </Form> </div> </div> ); }
截图显示currency枚举字段正常工作,但city和state字段异常,且表现存在不一致性,恳请提供解决方案。
内容的提问来源于stack exchange,提问作者MarvelCoder1142
相关产品推荐
相关产品推荐

