shadcn Input + Form + Zod “组件正在将不受控制的输入更改为受控制”

Ido*_*oBa 6 forms input reactjs zod

一点背景

我使用 shadcn ui 库和 Zod 在我的 Next.js React 应用程序中创建一些简单的表单。输入的类型selecttext

问题

我正在关注 shadcn 文档,了解如何使用 Zod 和 shadcn 的 ui 组件设置表单,但当输入值text发生更改时出现错误:

Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen.
Run Code Online (Sandbox Code Playgroud)

值得一提

仅当更改text(用户名)输入值时才会发生该错误。

此外,尽管出现错误,但表单仍能正常工作。

我尝试过的

我查了一下错误,发现答案说在 the 后面添加一个value或与一个钩子的组合,这解决了错误,但现在它不允许我提交表单。defaultValue{...field}useState('')

代码

'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, useState } 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),
  })
  
  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
Run Code Online (Sandbox Code Playgroud)

Ahm*_*set 8

出现这种情况是因为你没有defaultValues设置useForm

所以,defaultValues是未定义的。

那么当你使用时<FormField />你可能会这样写:

<FormField
  control={form.control}
  name="username"
  render={({ field }) => (
    <FormItem>
      <FormLabel>Username</FormLabel>
      <FormControl>
        <Input {...field} />
      </FormControl>
      <FormDescription>This is your public display name.</FormDescription>
      <FormMessage />
    </FormItem>
  )}
/>
Run Code Online (Sandbox Code Playgroud)

注意这一行<Input {...field} />

是、、、和field的对象。refvalueonChangeonBlurname

问题是,valueundefined你写任何字母时,它就会从未定义变为字符串。

您可以通过设置默认值轻松解决该问题

useForm({
  defaultValues: {
    username: ""
  }
})
Run Code Online (Sandbox Code Playgroud)