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

如何在不使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:23:28