使用 initialData 预填充查询
有时,你的应用中可能已经有查询的初始数据,你可以直接将其其提供给查询,当设置 initialData 选项后,查询会跳过初始加载状态!
initialData
会保留在缓存中,因此不建议为此选项提供占位符或不完整的数据,而应使用 placeholderData
const query = useQuery({
queryKey: ["users"],
queryFn: () => fetch("/users"),
initialData: initialUsers
});
stale 和 initialDataUpdatedAt
默认情况下,initialData 被视为 stale,这也意味着它将影响 staleTime 选项对其的解释方式。
如果你使用 initialSata 配置查询观察器,并且使用默认的 staleTime(默认值 0),则查询将在挂载时立即获取数据:
const query = useQuery({
queryKey: ["users"],
queryFn: () => fetch("/users"),
initialData: initialUsers
});
如果你使用 initialData
和 1000ms
的 staleTime
配置,则数据在 1000ms
内被视为新鲜的,就像是刚从服务器中获取到的一样。
const query = useQuery({
queryKey: ["users"],
queryFn: () => fetch("/users"),
initialData: initialUsers,
staleTime: 1000
});
如果你的 initialData 不是全新的怎么办?使用一个名为 initialDataUpdateAt 的选项。此选项允许你传递 initialData 本身上次更新时的时间戳(ms),例如 Date.now()提供的时间戳。
const query = useQuery({
queryKey: ["todos"],
queryFn: () => fetch("/todos"),
initialData: initialTodos,
staleTime: 60 * 1000, // 1 minute
// 这可以是10秒前,也可以是10分钟前
initialDataUpdateAt: initialTodoUpdatedTimestamp // eg: 1608412420052
});
初始数据函数
const query = useQuery({
queryKey: ["todos"],
queryFn: () => fetch("/todos"),
initialData: () => getExpensiveTodos()
});
来自缓存的初始数据
在某些情况下,你可以从另一个查询的缓存数据中获取初始数据。例如,从待办事项列的缓存中搜索单个待办事项,然后将其作为单个待办事项的初始数据:
const query = useQuery({
queryKey: ["todo", id],
queryFn: () => fetch("/todos"),
initialData: () => {
return queryClient.getQueryData(["todos"])?.find((d) => d.id === id);
}
});
来自 initialDataUpdateAt 从缓存中获取初始数据
从缓存中获取数据可能意味着数据已经过期了,建议将查询的 dataUpdateAt 传递给 initialDataUpdateAt ,而不是使用人为的 staleTime 来组织查询的重新获取,无论是否提供初始数据,这都会为查询实例提供所需的所有信息,以确定是否及何时需要重新获取查询。
const query = useQuery({
queryKey: ["todos", id],
queryFn: () => fetch("/todos"),
initialData: () => {
return queryClient.getQueryData(["todos"])?.find((d) => d.id === id);
},
initialDataUpdateAt: () => {
queryClient.getQueryState(["todos"])?.dataUpdatedAt;
}
});
来自缓存的条件初始数据
如果你用来查找初始数据的缓存已经过时了,此时你应该从服务器获取新的数据。而不是使用缓存中陈旧的数据。
const query = useQuery({
queryKey: ["todos", id],
queryFn: () => fetch(`/todos/${todoId}`),
initialData: () => {
return queryClient.getQueryData(["todos"])?.find((d) => d.id === id);
},
initialData: () => {
const state = queryClient.getQueryState(["todos"]);
// 如果查询存在并且数据不超过1分钟
if (state && Date.now() - state.dataUpdatedAt < 60 * 1000) {
return state.data.find((d) => d.id === id);
}
// 否则,返回 undefined 并且硬加载状态获取
}
});