Next.js中禁用React Query路由切换时自动重新获取数据
解决Next.js 13 + React Query 路由返回时自动重获数据的问题
核心问题分析
你遇到的自动重获问题,主要源于两个关键点:
- 若使用Next.js 13的App Router,
Giveaway组件未标记为客户端组件,导致每次路由返回时Server Component重新渲染,重复执行查询(此时React Query的客户端缓存配置完全不生效)。 - 缺少部分禁用自动重获的关键配置,即使组件是客户端类型,仍可能触发不必要的重获。
解决方案步骤
1. 将使用useQuery的组件转为客户端组件
在Giveaway.tsx最顶部添加'use client'指令——React Query的钩子只能在客户端组件中运行,这是Next.js 13 App Router的强制要求:
'use client'; // 必须添加这行 import { useGiveawayDetails } from './path-to-your-query-file'; // 其他导入代码... const Giveaway = () => { const { isLoading, isError, data, error, refetch } = useGiveawayDetails(); // 解构refetch用于手动触发 // 组件原有内容... } export default Giveaway
2. 完善查询配置,彻底禁用自动重获
修改useGiveawayDetails的配置,补充禁用网络重连时的自动重获,并根据需求调整数据新鲜度和定时重获规则:
export const useGiveawayDetails = () => useQuery(["giveawayDetails"], async () => { const response = await axios.get("/api/giveaway/giveaway-details") const data: giveawayDetails = await response.data; console.log(data); return data; }, { refetchOnWindowFocus: false, refetchOnMount: false, refetchOnReconnect: false, // 新增:禁止网络重连时自动重获 staleTime: Infinity, // 可选:设置数据永远不过期,避免因数据过期触发隐式重获 refetchInterval: false, // 若不需要定时重获,将原5分钟设置改为false onError: (error: any) => { if (error.response.status === 422 || error.response.status === 401) { toast(error.response.data.data.detail, { type: "error", toastId: "unauthorized" }); } else { toast(error.response.data.data.detail, { type: "error" }); } } }, );
3. 实现手动触发查询
从useQuery中解构出refetch函数,在需要的场景(比如按钮点击)调用它:
const Giveaway = () => { const { isLoading, isError, data, error, refetch } = useGiveawayDetails(); const handleManualRefetch = async () => { await refetch(); // 可选:添加重获成功提示 toast("数据已刷新", { type: "success" }); }; return ( <div className={styles.container}> <p className="text-600 text-md">Giveaways</p> {/* 添加手动刷新按钮 */} <button onClick={handleManualRefetch} disabled={isLoading}> {isLoading ? "刷新中..." : "手动刷新"} </button> {/* 原有渲染内容... */} </div> ) }
关键补充说明
- 若使用Next.js的Pages Router,无需添加
'use client',但仍需确保上述查询配置的完整性。 staleTime: Infinity会让React Query认为数据永远新鲜,若需要数据在一段时间后变旧但仍不自动重获,可设置具体时长(如24 * 60 * 60 * 1000表示1天)。
内容的提问来源于stack exchange,提问作者Bilal Mohammad
相关产品推荐
相关产品推荐

