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

T3 Stack中tRPC跨路由无效化非活跃查询的方案问询

T3 Stack + tRPC跨路由非活跃查询无效化解决方案

核心问题出在:离开/profile路由后,对应的查询会进入非活跃状态,默认情况下tRPC的invalidate()只会触发活跃查询重新获取,非活跃查询只会被标记为失效,但你设置了refetchOnMount: false,回到页面时不会主动拉取新数据,所以看不到更新。

下面是不用修改refetchOnMount: true或cacheTime: 0的解决方案:

方案1:精准定位查询键调用invalidate(推荐)

给invalidate()传入查询的具体参数,精准匹配要失效的缓存条目,哪怕查询处于非活跃状态也会被标记为失效。修改/student-profile里的onSuccess逻辑:

const acceptStudent = api.tasks.acceptStudent.useMutation({
    async onSuccess() {
        try {
            // 传入查询参数,精准命中目标缓存
            await utils.tasks.getInterestedTasksByAuthorId.invalidate({ authorId: user.id });
        } catch (e) {
            console.error(e);
        }
    },
});

然后把/profile里的refetchOnMount改成'if-stale'——这个配置刚好符合你的需求:只有当数据被标记为失效时,才会在挂载时重新请求,平时访问直接用缓存:

// /profile路由的useQuery配置调整
const {data: tasks, isFetching} = api.tasks.getInterestedTasksByAuthorId.useQuery({
    authorId: user.id
}, {
    refetchOnMount: 'if-stale', // 仅数据失效时重新请求
    refetchOnWindowFocus: false,
});

方案2:主动更新缓存

如果想直接把最新数据写入缓存,不需要等回到页面再请求,可以用fetchQuery主动拉取并更新缓存:

const acceptStudent = api.tasks.acceptStudent.useMutation({
    async onSuccess() {
        try {
            // 主动获取最新数据,直接覆盖缓存
            await api.tasks.getInterestedTasksByAuthorId.fetchQuery({ authorId: user.id });
        } catch (e) {
            console.error(e);
        }
    },
});

这样用户下次进入/profile时,直接读取更新后的缓存,完全不用额外请求。

原理说明

  • 不带参数的invalidate()会匹配所有同名查询,但非活跃查询只会被标记失效,不会立即更新。而你之前设置的refetchOnMount: false会阻止页面挂载时重新拉取失效数据,所以看不到变化。
  • 带参数的invalidate()能精准定位缓存条目,再配合refetchOnMount: 'if-stale',既保证了只有必要时才发请求,又能在数据失效时自动更新,完美平衡流量和体验。

内容的提问来源于stack exchange,提问作者Richard Biroš

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:35:20