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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:42:41