next.js 在T3堆栈内的tRPC中使非活动查询无效

2exbekwf  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(115)

我正在使用T3堆栈和tRPC,并面临着跨不同路由的查询无效的挑战。我的应用程序有两个路由:/profile/student-profile

  • On /profile:我显示一个包含特定任务(“TODO”项)数据的列表。
  • On /student-profile:用户可以使用两个按钮接受或拒绝学生的任务。

/student-profile上执行了一个突变(接受或拒绝学生)后,我需要使/profile上的任务列表数据无效,以相应地更新它。然而,即使突变成功,也不会触发无效,正如我的日志所证实的那样。
我意识到,当导航到/student-profile时,“list”查询变得不活动,从而防止无效。
这是我的限制:我想避免为这个查询设置refetchOnMount: truecacheTime: 0。原因是为了防止每次访问/profile页面时都进行额外的网络请求。这对于减少不必要的网络流量和改善用户体验至关重要。
我的问题是:在这个设置中,我如何有效地使来自另一个路由(/student-profile)的非活动查询(/profile上的列表)无效,同时遵守不频繁重新获取数据的约束?T3堆栈中的tRPC中是否有特定的方法来处理这种情况? 在这个问题上的任何指导或见解都将非常有帮助。 在此先谢谢您!/profile`路由

const {data: tasks, isFetching} = api.tasks.getInterestedTasksByAuthorId.useQuery({
    authorId: user.id
}, {
    refetchOnMount: false,
    refetchOnWindowFocus: false,
});

字符串
/student-profile路由

const acceptStudent = api.tasks.acceptStudent.useMutation({
        async onSuccess() {
            try {
                await utils.tasks.getInterestedTasksByAuthorId.invalidate()
            } catch (e) {
                console.error(e)
            }
        },
    });

const handleAcceptStudent = async () => {
        await acceptStudent.mutateAsync({
            studentId,
            taskId
        })
    }

332nm8kg

332nm8kg1#

如何有效地使非活动查询无效
有几种方法可以直接在你的mutation回调中做到这一点:

  • 失效需要filters,在这里你可以指定一个默认为'active'refetchType。将它设置为'all'来重新获取所有匹配的查询,即使是那些不活跃的查询:
utils.tasks.getInterestedTasksByAuthorId.invalidate(undefined, { refetchType: 'all' })

字符串
请注意,在trpc中,过滤器是第二个参数,因此如果没有输入,则需要将undefined作为第一个参数传递。

  • 你可以使用.refetch来代替.invalidate,这与使用refetchType: 'all'进行无效操作的效果几乎相同:
utils.tasks.getInterestedTasksByAuthorId.refetch()


这两种方法的问题在于,它们只针对它们匹配的 * 所有内容 *。这可能对您的情况有效,但让我们考虑一下,您的todo项目可以被过滤或搜索。由于react-query具有文档缓存,因此您将有多个缓存条目(每个输入一个),将匹配。所以,如果你有3个潜在的待办事项列表在你的缓存,都是不活动的,他们都将重新获取现场,即使用户可能永远不会回到它们。
这就是为什么无效通常是首选,它只会标记为过时的项目是不活跃的,只会重新获取他们的时候,用户请求他们下一次。
原因是为了防止每次访问/profile页面时都发出额外的网络请求。
事情是这样的:您不需要为此调整refetchOnMount之类的标志。为资源设置高staleTime是首选方法。如果您将staleTime设置为20分钟,这意味着数据将在20分钟内被认为是新鲜的,因此对useQuery的每次调用都只会在此时间段内从该高速缓存读取数据,因为像refetchOnMountrefetchOnWindowFocus等标志只会在事件发生时重新获取被认为过时的数据。
因为即使你将staleTime设置为Infinity(意思是:它将永远是新鲜的),调用invalidateQueries()本质上会覆盖它。
因此,我的首选方法是将所有标志保留在默认设置上,根据我的喜好定制staleTime,并使用默认的invalidate()方法,因为它需要编写和维护的代码量最少,用户体验最好,而且永远不会不必要地过度提取。

相关问题