如何不使用useEffect,通过useQuery更新React Hook Form?
解决useQuery数据未加载时React Hook Form默认值为空的问题
你当前的代码里,useForm会在组件初始化时就执行,而此时useQuery还没拿到currentPerson数据,所以默认值只能是空字符串。不用非得依赖useEffect,有几种更直接的解决方式:
方法一:延迟初始化表单
等currentPerson数据加载完成后再初始化useForm,避免默认值为空。可以用条件判断实现:
const currentUserId = '1'; const { data: currentPerson } = useQuery({ queryKey: ['person', currentUserId], queryFn: ({ queryKey }) => { const [, id] = queryKey; return fetchPerson(id); }, }); // 只有拿到数据才初始化表单 let form; if (currentPerson) { form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { email: currentPerson.email, phone: currentPerson.phone, }, }); } // TSX部分,数据未加载时显示加载状态 if (!form) return <div>加载中...</div>; <Form {...form}> <form> {/* 表单字段 */} </form> </Form>
也可以用useMemo来封装这个逻辑:
const form = useMemo(() => { if (!currentPerson) return null; return useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { email: currentPerson.email, phone: currentPerson.phone, }, }); }, [currentPerson]);
方法二:用useQuery的onSuccess回调重置表单
先初始化一个空值的表单,等useQuery成功获取数据后,调用form的reset方法填充真实数据,完全不需要useEffect:
const currentUserId = '1'; // 先初始化空表单 const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { email: '', phone: '', }, }); const { data: currentPerson } = useQuery({ queryKey: ['person', currentUserId], queryFn: ({ queryKey }) => { const [, id] = queryKey; return fetchPerson(id); }, // 数据获取成功后直接重置表单 onSuccess: (data) => { form.reset({ email: data.email, phone: data.phone, }); }, }); // TSX部分 <Form {...form}> <form> {/* 表单字段 */} </form> </Form>
这两种方法都能避免表单一开始就被填充为空字符串的问题,比用useEffect更贴合React Query和React Hook Form的设计逻辑。
内容的提问来源于stack exchange,提问作者wyc
相关产品推荐
相关产品推荐

