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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 16:07:51