如何在不使用useEffect时将TanStack useQuery结果设为表单状态默认值?
解决方案
在这个场景下,用useEffect同步查询结果到表单状态并非严格的反模式,但确实有更优雅、更精准的替代方案,以下是具体实现:
1. 优先使用useQuery的onSuccess回调
直接在useQuery配置中指定onSuccess函数,当请求成功获取到默认值时,直接更新表单状态。这种方式只会在查询成功时触发,避免了useEffect可能带来的多余渲染或意外触发:
type TFormState = { field1: string | null; field2: string | null; field3: string | null; }; const Detail = () => { const { currentId } = useParams(); const [formState, setFormState] = useState<TFormState>({ field1: null, field2: null, field3: null, }); const defaultValues = useQuery({ queryKey: ["getDefaultFormValues", currentId], queryFn: () => { if (!currentId) { return Promise.reject(new Error("No well id")); } return fetchDefaults(); }, enabled: !!currentId, refetchInterval: false, // 请求成功时同步表单状态 onSuccess: (data) => { setFormState(data); } }); // 表单渲染示例:绑定formState和更新函数 return ( <div> <input value={formState.field1 ?? ''} onChange={(e) => setFormState(prev => ({...prev, field1: e.target.value}))} /> {/* 其他字段同理 */} </div> ); };
2. 结合表单库(如react-hook-form)使用reset方法
如果项目中使用表单库,推荐用库自带的reset方法来初始化表单,这是更贴合表单管理场景的做法:
import { useForm } from 'react-hook-form'; type TFormState = { field1: string | null; field2: string | null; field3: string | null; }; const Detail = () => { const { currentId } = useParams(); const { register, reset, formState: { values } } = useForm<TFormState>({ defaultValues: { field1: null, field2: null, field3: null } }); const defaultValues = useQuery({ queryKey: ["getDefaultFormValues", currentId], queryFn: () => { if (!currentId) { return Promise.reject(new Error("No well id")); } return fetchDefaults(); }, enabled: !!currentId, refetchInterval: false, onSuccess: (data) => { // 用查询结果重置表单 reset(data); } }); // 表单渲染示例:使用register绑定字段 return ( <div> <input {...register('field1')} /> <input {...register('field2')} /> <input {...register('field3')} /> </div> ); };
3. 若坚持使用useEffect的注意事项
如果一定要用useEffect,确保只在查询数据变化时触发,避免不必要的表单重置:
// 在组件内添加以下代码 useEffect(() => { // 仅当数据存在时更新表单 if (defaultValues.data) { setFormState(defaultValues.data); } }, [defaultValues.data]); // 仅依赖查询结果,避免多余触发
需要注意:如果currentId变化导致查询重新执行,表单会被重置为新的默认值,若这不符合业务需求,需额外添加判断逻辑(比如仅在组件首次挂载时同步)。
内容的提问来源于stack exchange,提问作者DylalyD
相关产品推荐
相关产品推荐

