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

使用Axios+TanstackQuery时请求成功但AxiosResponse.data为undefined

问题分析与解决方案

核心问题出在Axios泛型参数的误用,导致你拿到的query.data并不是完整的Axios响应对象,而是直接对应响应的data字段类型,所以再访问.data自然会得到undefined。

为什么非泛型版本正常?

非泛型版本中,你可能没有指定Axios的泛型参数,或者显式指定了AxiosResponse<具体数据类型>,此时query.data是完整的Axios响应对象,包含data属性,所以能正常取值。而泛型版本中,你把<T>传给了axios.get,但Axios的get方法泛型参数默认指代的是响应体data的类型,而非整个响应对象的类型。


解决方案1:保留完整Axios响应对象

如果你需要获取完整的Axios响应(比如headers、status等),需要显式指定泛型为AxiosResponse<T>:

import { AxiosResponse } from 'axios';

const fetchDataService = <T>(key: string, url: string, enabled: boolean): Service<T> => {
    const [result, setResult] = useState<Service<T>>({ status: ServiceStatus.LOADING });
    const { apiBaseEndpoint } = useContext(ApiEndpointsContext);

    const query = useQuery({
        queryKey: [key],
        retry: false,
        enabled,
        staleTime: 1000 * 10,
        // 指定泛型为AxiosResponse<T>,此时query.data是完整的响应对象
        queryFn: async ({ signal }) => await axios.get<AxiosResponse<T>>(`${apiBaseEndpoint}${url}`, { signal })
    });

    useEffect(() => {
        if (query.isLoading || query.isFetching) return;

        if (query.isError) {
            setResult({
                status: ServiceStatus.ERROR,
                error: query.error as Error
            });
            return;
        }

        const axiosResponse = query.data;
        if (!axiosResponse) {
            setResult({
                status: ServiceStatus.ERROR,
                error: new Error('Unknown error occurred when fetching data')
            });
            return;
        }

        // 此时可以正常访问axiosResponse.data
        setResult({
            status: ServiceStatus.SUCCESS,
            payload: axiosResponse.data
        });
    }, [query.isFetching, query.isLoading, query.isError, query.data, query.error]);

    return result;
};

解决方案2:直接返回响应数据(推荐)

通常我们只需要响应体的data字段,此时可以让Axios直接返回data,简化后续逻辑:

const fetchDataService = <T>(key: string, url: string, enabled: boolean): Service<T> => {
    const [result, setResult] = useState<Service<T>>({ status: ServiceStatus.LOADING });
    const { apiBaseEndpoint } = useContext(ApiEndpointsContext);

    const query = useQuery({
        queryKey: [key],
        retry: false,
        enabled,
        staleTime: 1000 * 10,
        // 泛型T指代响应data的类型,直接返回response.data
        queryFn: async ({ signal }) => {
            const response = await axios.get<T>(`${apiBaseEndpoint}${url}`, { signal });
            return response.data;
        }
    });

    useEffect(() => {
        if (query.isLoading || query.isFetching) return;

        if (query.isError) {
            setResult({
                status: ServiceStatus.ERROR,
                error: query.error as Error
            });
            return;
        }

        if (!query.data) {
            setResult({
                status: ServiceStatus.ERROR,
                error: new Error('Unknown error occurred when fetching data')
            });
            return;
        }

        // 直接用query.data作为payload,无需再访问.data属性
        setResult({
            status: ServiceStatus.SUCCESS,
            payload: query.data
        });
    }, [query.isFetching, query.isLoading, query.isError, query.data, query.error]);

    return result;
};

额外优化:去掉冗余的状态同步

React Query本身已经维护了请求状态,你完全不需要用useState和useEffect同步状态,可以直接根据query的状态返回结果,简化代码:

const fetchDataService = <T>(key: string, url: string, enabled: boolean): Service<T> => {
    const { apiBaseEndpoint } = useContext(ApiEndpointsContext);

    const query = useQuery({
        queryKey: [key],
        retry: false,
        enabled,
        staleTime: 1000 * 10,
        queryFn: async ({ signal }) => {
            const response = await axios.get<T>(`${apiBaseEndpoint}${url}`, { signal });
            return response.data;
        }
    });

    if (query.isLoading || query.isFetching) {
        return { status: ServiceStatus.LOADING };
    }

    if (query.isError) {
        return {
            status: ServiceStatus.ERROR,
            error: query.error as Error
        };
    }

    if (!query.data) {
        return {
            status: ServiceStatus.ERROR,
            error: new Error('Unknown error occurred when fetching data')
        };
    }

    return {
        status: ServiceStatus.SUCCESS,
        payload: query.data
    };
};

这样既避免了状态不同步的风险,代码也更简洁。

内容的提问来源于stack exchange,提问作者Zahand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:45:56