使用Shadcn+Zod+Next.js表单时出现受控/非受控输入警告
解决React Hook Form + Shadcn UI中Input从非受控转受控的警告
问题原因
你遇到的警告是因为username字段在useForm初始化时未设置初始值,导致Input组件的value一开始为undefined(非受控状态),用户输入内容后value变为字符串(受控状态),React检测到这种状态切换后抛出警告。
解决方案
无需额外使用useState,直接在useForm的配置项中添加defaultValues,给username设置初始空字符串,让组件从一开始就处于受控状态:
const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), defaultValues: { // 新增默认值配置 email: undefined, username: "" } })
修改后的完整代码
'use client' import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { useForm } from 'react-hook-form' import { zodResolver } from "@hookform/resolvers/zod" import * as z from "zod" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { toast } from "@/components/ui/use-toast" import Link from "next/link" import { Input } from "@/components/ui/input" import { ReactNode } from "react" const FormSchema = z.object({ email: z .string({ required_error: "Please select an email to display.", }) .email(), username: z.string(), }) const ZodForm = () => { const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), defaultValues: { email: undefined, username: "" } }) function onSubmit(data: z.infer<typeof FormSchema>) { console.log(data); toast({ title: "You submitted the following values:", description: ( <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4"> <code className="text-white">{JSON.stringify(data, null, 2)}</code> </pre> ), }) } return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6"> <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <Select onValueChange={field.onChange} defaultValue={field.value}> <FormControl> <SelectTrigger> <SelectValue placeholder="Select a verified email to display" /> </SelectTrigger> </FormControl> <SelectContent> <SelectItem value="m@example.com">m@example.com</SelectItem> <SelectItem value="m@google.com">m@google.com</SelectItem> <SelectItem value="m@support.com">m@support.com</SelectItem> </SelectContent> </Select> <FormDescription> You can manage email addresses in your{" "} <Link href="/examples/forms">email settings</Link>. </FormDescription> <FormMessage /> </FormItem> )} /> <FormField control={form.control} name={'username'} render={({ field }) => ( <FormItem> <FormLabel>Username</FormLabel> <FormControl> <Input placeholder="shadcn" {...field} /> </FormControl> <FormDescription> This is your public display name. </FormDescription> <FormMessage /> </FormItem> )} /> <button type="submit">Submit</button> </form> </Form> ) } export default ZodForm
为什么之前的尝试失败
你之前用useState手动设置value或defaultValue,覆盖了React Hook Form提供的field.value,导致表单状态脱离了RHF的控制,提交时无法获取正确的字段值。
内容的提问来源于stack exchange,提问作者IdoBa
相关产品推荐
相关产品推荐

