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

如何在React Hook Form客户端组件中从数据库预取并设置默认值?

解决shadcn Select组件异步设置react-hook-form默认值的问题

要实现从数据库异步预取默认值并同步到表单,你可以按以下步骤调整代码:

  1. 新增异步数据获取逻辑:用useEffect发起请求拉取数据库中的默认值
  2. 手动更新表单字段:数据返回后调用react-hook-form的setValue方法设置对应字段值
  3. 处理加载状态:避免在数据未返回时渲染未初始化的表单

修改后的完整代码示例:

"use client"

import { useEffect, useState } from "react"
import Link from "next/link"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"

import { Button } from "@/components/ui/button"
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { toast } from "@/components/ui/use-toast"

const FormSchema = z.object({
  email: z
    .string({
      required_error: "请选择一个要显示的邮箱。",
    })
    .email(),
})

export function SelectForm() {
  const [isLoading, setIsLoading] = useState(true)
  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    // 先设置空默认值,后续异步更新
    defaultValues: {
      email: ""
    }
  })

  // 模拟从数据库异步获取默认值
  useEffect(() => {
    const fetchDefaultEmail = async () => {
      try {
        // 替换为你实际的接口请求
        const res = await fetch("/api/user/default-email")
        const data = await res.json()
        // 同步表单字段值
        form.setValue("email", data.defaultEmail)
      } catch (err) {
        console.error("获取默认邮箱失败:", err)
      } finally {
        setIsLoading(false)
      }
    }

    fetchDefaultEmail()
  }, [form.setValue])

  function onSubmit(data: z.infer<typeof FormSchema>) {
    toast({
      title: "你提交了以下内容:",
      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>
      ),
    })
  }

  if (isLoading) {
    return <div>加载中...</div>
  }

  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>邮箱</FormLabel>
              <Select onValueChange={field.onChange} defaultValue={field.value}>
                <FormControl>
                  <SelectTrigger>
                    <SelectValue placeholder="选择一个已验证的邮箱进行显示" />
                  </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>
                你可以在你的{" "}
                <Link href="/examples/forms">邮箱设置</Link>中管理邮箱地址。
              </FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">提交</Button>
      </form>
    </Form>
  )
}

核心说明:

  • 异步获取+setValue同步:组件挂载后发起请求,数据返回后用setValue直接更新表单字段,这是异步设置默认值的关键
  • 初始空值+加载状态:先给字段设置空值避免初始化时触发校验错误,加载状态提升用户体验
  • 依赖项管理:把form.setValue加入useEffect依赖,确保更新逻辑的正确性

内容的提问来源于stack exchange,提问作者Marc Willhaus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:43:22