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

使用Next.js <Link>跨页面更新数据的问题及解决方案咨询

解决方案:解决Next.js 预取导致tRPC缓存未更新的问题

1. 全面失效关联查询的tRPC缓存

你之前仅失效单个端点缓存,但数据变更会影响多个关联查询,必须同时失效所有相关端点的缓存。注意tRPC的缓存是基于「端点+查询参数」的键值对,失效时需匹配查询参数,或直接失效整个端点的所有缓存:

比如在更新场景的mutation中:

const updateScene = api.scene.update.useMutation({
  async onSuccess(_, { sceneId, projectId }) {
    // 失效当前页面用到的scene查询(匹配参数)
    await api.scene.getByProjectIdElements.invalidate({ projectId });
    // 失效scheduleboard页面用到的project查询(匹配参数)
    await api.project.getById.invalidate({ id: projectId });
    // 若参数不确定,直接失效整个端点的所有缓存
    // await api.scene.getByProjectIdElements.invalidate();
    // await api.project.getById.invalidate();
  },
});

2. 按需禁用预取

对数据更新频繁的页面链接,添加prefetch={false}属性,避免预取旧数据,同时保留客户端导航的速度优势:

<Link href={`/scenes/${sceneId}`} prefetch={false}>
  场景详情
</Link>

3. 调整查询的缓存过期策略

给易变的查询设置staleTime: 0,让组件每次挂载都自动检查并获取最新数据,即使有预取缓存也会强制更新:

// scheduleboard.tsx 示例
const { data: projectData } = api.project.getById.useQuery(
  { id: projectId },
  { enabled: !!projectId, staleTime: 0 }
);

4. 确保全局共享tRPC客户端缓存

检查是否每个页面都独立创建了tRPC客户端实例——若如此会导致缓存隔离,mutation的失效操作无法跨页面生效。需在_app.tsx中通过withTRPC高阶组件全局注入客户端,让所有页面共享同一缓存池:

// _app.tsx
import { withTRPC } from '@trpc/next';
import { createTRPCNext } from '@trpc/next';
import { appRouter } from '../server/trpc/router';

const trpc = createTRPCNext({
  config() {
    return {
      url: '/api/trpc',
    };
  },
});

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default trpc.withTRPC(MyApp);

为什么之前的invalidate没生效?

核心原因通常是两个:

  • 仅失效了单个端点,未覆盖关联的其他查询(比如更新场景后,project.getById的缓存也需要失效);
  • invalidate时的参数和查询时的参数不匹配,tRPC无法定位到对应的缓存条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:50:16