如何为Zod校验的React Hook Form设置动态用户ID默认值
解决方案
首先先修正你代码里的一个关键错误:获取用户数据时,你拿到的是res.status(HTTP状态码),而不是用户的实际数据,应该改成:
const res = await fetch('/api/get-user', { method: 'GET' }); const data = await res.json(); // 这里才是用户数据 setUser(data);
接下来针对「无法在组件外的defaultValues中设置当前userId」的问题,提供三种可行方案:
方案1:组件内部动态生成defaultValues,结合条件渲染初始化表单
把defaultValues移到组件内部,等user数据加载完成后再初始化表单,确保userId能正确传入:
export default function Page() { const [user, setUser] = useState<any>(); const [url, setUrl] = useState<string | null>(null); useEffect(() => { const checkIsUser = async () => { const res = await fetch('/api/get-user', { method: 'GET' }); const data = await res.json(); // 修正:获取实际用户数据 setUser(data); }; checkIsUser(); }, []); // 未获取到用户时显示加载或执行重定向 if (!user) { // 若使用Next.js客户端组件,需用useRouter跳转: // const router = useRouter(); // router.push('/login'); return <div>加载中...</div>; } // 动态生成包含userId的defaultValues const defaultValues: Partial<ProfileFormValues> = { can_share: true, userId: user.id // 直接使用已加载的用户ID }; const form = useForm<ProfileFormValues>({ resolver: zodResolver(profileFormSchema), defaultValues, mode: 'onChange', }); // 其余onSubmit、handleCopy等代码保持不变 }
方案2:使用useForm的reset方法,在用户加载后补全userId
如果不想延迟表单初始化,可以先初始化基础表单,等user数据加载完成后用reset方法更新userId字段:
export default function Page() { const [user, setUser] = useState<any>(); const [url, setUrl] = useState<string | null>(null); // 先初始化不含userId的基础defaultValues const defaultValues: Partial<ProfileFormValues> = { can_share: true }; const form = useForm<ProfileFormValues>({ resolver: zodResolver(profileFormSchema), defaultValues, mode: 'onChange', }); useEffect(() => { const checkIsUser = async () => { const res = await fetch('/api/get-user', { method: 'GET' }); const data = await res.json(); setUser(data); // 用户数据加载后,重置表单并设置userId form.reset({ ...form.getValues(), // 保留现有表单输入值 userId: data.id }); }; checkIsUser(); }, [form]); // 依赖form实例确保方法可用 if (!user) { return <div>加载中...</div>; } // 其余代码保持不变 }
方案3:服务器端预获取用户(Next.js场景)
如果你的项目基于Next.js,可以用服务器组件先获取用户信息,再传递给客户端组件,这样表单初始化时就能直接拿到userId:
服务器组件(page.tsx)
import { cookies } from 'next/headers'; import ProfileForm from './ProfileForm'; // 客户端组件 import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'; export default async function Page() { // 服务器端通过Supabase获取用户 const supabase = createServerComponentClient({ cookies }); const { data: { user } } = await supabase.auth.getUser(); if (!user) { redirect('/login'); // 服务器端直接重定向 } return <ProfileForm userId={user.id} />; }
客户端组件(ProfileForm.tsx)
'use client'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; type Props = { userId: string; }; export default function ProfileForm({ userId }: Props) { const defaultValues: Partial<ProfileFormValues> = { can_share: true, userId: userId // 直接使用服务器传递的用户ID }; const form = useForm<ProfileFormValues>({ resolver: zodResolver(profileFormSchema), defaultValues, mode: 'onChange', }); // 其余代码保持不变 }
内容的提问来源于stack exchange,提问作者hey
相关产品推荐
相关产品推荐

