为何tRPC的invalidateQueries不接受trpc.router.endpoint.queryKey()生成的完整查询键?
嗨,我来帮你捋捋这个踩坑问题!你遇到的情况其实是因为tRPC的queryKey()方法返回的是带内部元数据的完整键,但React Query的查询缓存里存的并不是这个完整数组,导致匹配不上。
咱们拆解一下:你用trpc.like.getLikesByUser.queryKey()得到的是[['like', 'getLikesByUser'], { type: 'query' }],这里面第二个元素{ type: 'query' }是tRPC自己加的内部标记,用来区分查询(query)和突变(mutation),但React Query实际存储的查询键只有前半部分——也就是['like', 'getLikesByUser'](如果你的查询没有传参数的话)。
当你用完整的数组去调用invalidateQueries时,React Query会严格匹配每一个元素,包括那个内部对象(对象匹配是引用相等,就算内容一样也匹配不上),自然找不到对应的查询,也就没法 invalidate 了。
给你几个靠谱的解决办法:
方法一:手动提取有效查询键部分
直接取queryKey()返回数组的第一个元素,也就是实际的查询路径:
const likeValidKey = trpc.like.getLikesByUser.queryKey()[0]; await queryClient.invalidateQueries({ queryKey: likeValidKey });
如果你的查询需要传参数(比如useQuery({ userId: 123 })),那还要把参数加进去:
const likeValidKey = [...trpc.like.getLikesByUser.queryKey()[0], { userId: 123 }]; await queryClient.invalidateQueries({ queryKey: likeValidKey });
方法二:用tRPC自带的invalidate方法(更推荐)
其实tRPC已经给每个端点封装了invalidate方法,它会自动处理正确的查询键,不用你手动拆解,省心又不容易错:
// 不带参数的情况 await trpc.like.getLikesByUser.invalidate(); // 带参数的情况,精准 invalidate 特定参数的查询 await trpc.like.getLikesByUser.invalidate({ userId: 123 });
简单来说,别直接用queryKey()返回的完整数组去调用React Query的invalidateQueries,要么拆出有效部分,要么直接用tRPC提供的封装方法,这样就能解决问题啦!
备注:内容来源于stack exchange,提问作者TadeoGavensky

