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