名称: TanStack查询常见陷阱 描述: “TanStack Query v5 常见模式和陷阱。适用于实现数据获取、缓存失效或调试陈旧数据问题。触发条件:useQuery、useMutation、queryKey、invalidate、TanStack、React Query。”
TanStack Query v5 常见陷阱
TanStack Query v5 的常见陷阱和正确模式。
何时使用
- 使用 useQuery 实现数据获取时
- 使用 useMutation 设置数据变更时
- 调试陈旧数据或缓存问题时
- 审查使用 TanStack Query 的代码时
- 从 v4 迁移到 v5 时
工作流程
步骤 1:检查查询键
验证查询键是否使用完整的 URL 路径以确保正确的去重。
步骤 2:验证失效机制
确保数据变更操作在成功后使相关查询失效。
步骤 3:检查 v5 特定模式
验证 v5 特定模式(isPending 与 isLoading 的区别)。
正确用法
// ✅ 正确:在 queryKey 中使用完整的 URL 路径
const { data } = useQuery({
queryKey: ['/api/strategies', strategyId],
queryFn: () => api.get(`/api/strategies/${strategyId}`),
});
// ✅ 正确:数据变更后使查询失效
const mutation = useMutation({
mutationFn: (data) => api.post('/api/strategies', data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['strategies'] });
},
});
// ✅ 正确:使用模式类型对响应进行类型标注
import type { Strategy } from '@shared/schema';
const { data } = useQuery<{ data: Strategy[] }>(...);
反模式
// ❌ 错误:查询键过短
queryKey: ['strategy'] // 无法正确去重
// ❌ 错误:忘记使查询失效
onSuccess: () => { navigate('/'); } // 缓存陈旧!
// ❌ 错误:在 v5 中对数据变更使用 isLoading
mutation.isLoading // v5 中应使用 isPending
乐观更新
// ✅ 立即更新 UI,出错时回滚
const mutation = useMutation({
mutationFn: updateStrategy,
onMutate: async (newData) => {
await queryClient.cancelQueries({ queryKey: ['strategy', id] });
const previous = queryClient.getQueryData(['strategy', id]);
// 乐观更新
queryClient.setQueryData(['strategy', id], newData);
return { previous };
},
onError: (err, newData, context) => {
// 出错时回滚
queryClient.setQueryData(['strategy', id], context.previous);
toast.error('更新失败');
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['strategy', id] });
},
});
快速检查清单
- [ ] 查询键使用完整的 URL 路径
- [ ] 数据变更操作使相关查询失效
- [ ] 在 v5 中对数据变更使用 isPending(而非 isLoading)
- [ ] 响应使用模式类型进行类型标注