查询键
TanStack Query 的核心功能之一是基于查询键(query keys)为你管理查询缓存。查询键在顶层必须是一个数组,可以简单到仅包含单个字符串的数组,也可以复杂到由多个字符串和嵌套对象组成的数组。只要该查询键能通过 JSON.stringify 序列化,且对该查询所获取的数据具有唯一性,你就可以使用它!
简单查询键
最简单的查询键形式是仅含常量值的数组。这种格式适用于:
- 通用列表/索引资源
- 非层级结构的资源
TypeScript
1// A list of todos2useQuery(() => () => ({ queryKey: ['todos'], ... }))3 4// Something else, whatever!5useQuery(() => () => ({ queryKey: ['something', 'special'], ... }))带变量的数组查询键
当查询需要更多信息才能唯一描述其数据时,你可以使用一个包含字符串及任意数量可序列化对象的数组来描述它。这种形式适用于:
- 层级结构或嵌套资源
- 通常会传入 ID、索引或其他基础类型,以唯一标识某项数据
- 带有额外参数的查询
- 通常会传入一个包含额外选项的对象
TypeScript
1// An individual todo2useQuery(() => () => ({ queryKey: ['todo', 5], ... }))3 4// An individual todo in a "preview" format5useQuery(() => () => ({ queryKey: ['todo', 5, { preview: true }], ...}))6 7// A list of todos that are "done"8useQuery(() => () => ({ queryKey: ['todos', { type: 'done' }], ... }))查询键以确定性方式哈希!
这意味着,无论对象中键的顺序如何,以下所有查询均被视为相等:
TypeScript
1useQuery(() => () => ({ queryKey: ['todos', { status, page }], ... }))2useQuery(() => () => ({ queryKey: ['todos', { page, status }], ...}))3useQuery(() => () => ({ queryKey: ['todos', { page, status, other: undefined }], ... }))但以下查询键则不相等——数组元素的顺序至关重要!
TypeScript
1useQuery(() => () => ({ queryKey: ['todos', status, page], ... }))2useQuery(() => () => ({ queryKey: ['todos', page, status], ...}))3useQuery(() => () => ({ queryKey: ['todos', undefined, page, status], ...}))若你的查询函数依赖某个变量,请将其包含在查询键中
由于查询键需唯一描述其所拉取的数据,因此应包含查询函数中任何会发生变化的变量。例如:
TypeScript
1function Todos(props) {2 const todosQuery = useQuery(() => () => ({3 queryKey: ['todos', props.todoId],4 queryFn: () => fetchTodoById(props.todoId),5 }))6}请注意,查询键充当查询函数的依赖项。将相关变量加入查询键,可确保查询被独立缓存;并且每当变量发生变化时,查询将自动重新拉取(具体行为取决于你的 staleTime 设置)。更多说明与示例,请参阅 exhaustive-deps 章节。
延伸阅读
如需了解如何在大型应用中组织查询键,可参考 Effective TanStack Query Keys,并查阅 Community Resources 中提供的 Query Key Factory Package。