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

React Query重复发起请求未使用缓存问题排查

React Query 缓存未命中问题:下滑滑块时重复请求相同URL数据

问题背景

开发了一个带滑块的React应用,用于展示视频缩略图,滑块具备「上滑」「下滑」按钮切换内容。因接口限制单次最多返回25条数据,滑块会按需触发新请求。选用React Query是看中其缓存能力,期望上滑请求的数据,下滑时直接调用缓存无需重复请求,但实际下滑时仍会重新发起请求。

相关配置与代码

1. 自定义useQueryClient钩子(QueryClient默认配置)

const useQueryClient = () => {
    const { showError, completeLoading } = useDispatchAction();

    const queryErrorHandler = (err: unknown): void => {
        const axiosError = err as AxiosError;
        completeLoading();
        showError({ isError: true, errorMessage: axiosError.message });
    };

    const defaultQueryClientOptions = {
        queries: {
            onError: queryErrorHandler,
            retry: false,
            cacheTime: 1.1 * (60 * 1000),
            refetchOnMount: false,
            refetchOnWindowFocus: false,
            staleTime: 1 * (60 * 1000),
            refetchInterval: 1 * (60 * 1000),
        },
    };

    return new QueryClient({
        defaultOptions: defaultQueryClientOptions,
    });
};

export default useQueryClient;

2. TanstackQueryProvider组件

import { QueryClientProvider } from "@tanstack/react-query";
import { useDispatchAction, useQueryClient } from "hooks";
import { QueryClient } from "@tanstack/react-query";
import React from "react";
import { ReactNode } from "react";
import { AxiosError } from "axios";

export const TanstackQueryProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
    // const queryClient = useQueryClient();

    const { showError, completeLoading } = useDispatchAction();

    const queryErrorHandler = (err: unknown): void => {
        const axiosError = err as AxiosError;
        completeLoading();
        showError({ isError: true, errorMessage: axiosError.message });
    };

    const defaultQueryClientOptions = {
        queries: {
            onError: queryErrorHandler,
            retry: false,
            cacheTime: 1.1 * (60 * 1000),
            refetchOnMount: false,
            refetchOnWindowFocus: false,
            staleTime: 1 * (60 * 1000),
            refetchInterval: 1 * (60 * 1000),
        },
    };

    const [queryClient] = React.useState(
        () =>
            new QueryClient({
                defaultOptions: defaultQueryClientOptions,
            })
    );

    return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
};

export default TanstackQueryProvider;

3. 应用入口文件

const container = document.getElementById("root");
const root = createRoot(container as Element);
root.render(
    <AppProvider>
        <TanstackQueryProvider>
            <App />
        </TanstackQueryProvider>
    </AppProvider>
);

4. 查询逻辑代码

const { isLoading, data, refetch, isFetching, isPreviousData } = useQuery({
    queryKey: ["users", url],
    queryFn: () => fetchThumbnails(url),
    enabled: Boolean(url),
    keepPreviousData: true,
});

5. 实际请求函数

export const fetchThumbnails = async (url: string) => {
    const response = await fetch(url);
    if (!response.ok) {
        const status = response.status;
        const result = await response.json();
        throw new Error(`${status} ${result?.error?.message || "unknown error"}`);
    }
    const data = response.json();
    console.log("url", url); 
    return data;
};

核心疑问

已确认上下滑动时的URL完全相同,理论上应匹配同一缓存键,但为何未命中缓存?


问题排查与解决方案

1. 移除自动刷新配置

默认配置中设置了refetchInterval: 1 * (60 * 1000),该配置会让React Query每隔60秒自动重新请求数据,即使数据处于新鲜期(staleTime内)也会触发请求。若无需定时刷新,直接删除该配置即可。

2. 修复请求函数的异步逻辑

请求函数中response.json()未添加await,会导致返回Promise而非实际数据,可能引发缓存解析异常。修正代码:

export const fetchThumbnails = async (url: string) => {
    const response = await fetch(url);
    if (!response.ok) {
        const status = response.status;
        const result = await response.json();
        throw new Error(`${status} ${result?.error?.message || "unknown error"}`);
    }
    const data = await response.json(); // 添加await
    console.log("url", url); 
    return data;
};

3. 确认queryKey的绝对一致性

即使URL看起来相同,需检查是否存在编码差异、空格、参数顺序不一致等情况。可在组件内打印queryKey的字符串化结果,对比上下滑时的缓存键是否完全一致。

4. 验证QueryClient实例唯一性

确保整个应用中只有一个QueryClient实例,可在TanstackQueryProvider创建实例时添加日志,确认实例未被重复创建。

5. 借助DevTools查看缓存状态

安装React Query DevTools,直观查看缓存中的queryKey及对应数据状态,确认相同queryKey是否存在有效缓存,以及是否被标记为需重新请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:10:00