Next.js+React Query:URL参数变化时复用组件如何重新获取数据?
问题:Next.js14 + React Query5 组件复用下URL变化时数据不更新
组件代码
// UserProfile.tsx const UserProfile = ({id}) => { const {data: userData} = useUser(id); console.log(userData.id); // 组件运行时会打印此内容 return <> {/* UserDetail包含多个使用fetch的钩子 */} <UserDetail userId={userData.id} /> </> } // useUser.tsx export const useUser = (userId) => { return useQuery({ queryKey: ['user'], queryFn: async () => { await getUser(userId); // fetch }, gcTime: 0, // 页面切换时清除缓存 staleTime: 0, }) }
问题现象
- 使用
<Link />从/user/1跳转到/user/2,URL变化后用户2的数据正常显示,但console.log打印undefined - 点击浏览器返回按钮回到
/user/1,URL变回/user/1,但页面仍显示用户2的数据 - 此时
console.log先打印2(执行了useUser(2)),之后打印1但未执行useUser(1) - 移除
gcTime后,甚至连跳转到/user/2时都无法显示用户2的数据
推测原因
使用<Link />跳转时组件会卸载,React Query执行垃圾回收;但返回按钮不会卸载组件,无垃圾回收,导致userData仍保留旧值,进而调用了错误的useUser(2)
解决方案
1. 修正React Query的queryKey,加入userId作为依赖
React Query通过queryKey区分不同的查询缓存,当前queryKey: ['user']没有包含userId,导致不同用户的查询共用同一个缓存键,复用组件时不会触发新的查询。同时原queryFn漏写了返回语句,会导致userData为undefined,需一并修正:
export const useUser = (userId) => { return useQuery({ queryKey: ['user', userId], // 将userId加入queryKey,区分不同用户的缓存 queryFn: async () => { return getUser(userId); // 必须返回请求到的数据 }, staleTime: 0, // 移除gcTime:0,避免缓存被立即回收,默认gcTime为5分钟,可按需调整 }) }
2. 确保组件接收的id是最新路由参数
在Next.js14的App Router中,页面组件需从params中获取最新的URL参数,并传递给UserProfile,确保组件拿到的id是当前路由的用户ID:
// app/user/[id]/page.tsx import UserProfile from './UserProfile'; export default function UserPage({ params }) { return <UserProfile id={params.id} />; }
3. 可选:强制触发重新查询
如果需要在路由变化时强制刷新数据,可在useQuery中添加配置:
useQuery({ // 其他配置... refetchOnMount: true, // 组件挂载时重新查询 refetchOnWindowFocus: false // 按需关闭窗口聚焦时的自动重查 })
内容的提问来源于stack exchange,提问作者Téwa
相关产品推荐
相关产品推荐

