react-query 基本使用介绍
useQuery
使用查询
- queryKey 查询键 查询键必须是可序列化的 只要键改变,React-Query 就会自动触发重新获取。
Use Query Key Factories
const todoKeys = {
all: ['todos'] as const,
lists: () => [...todoKeys.all, 'list'] as const,
list: (filters: string) => [...todoKeys.lists(), { filters }] as const,
details: () => [...todoKeys.all, 'detail'] as const,
detail: (id: number) => [...todoKeys.details(), id] as const,
}
每个级别都建立在另一个级别之上
// 🕺 remove everything related to the todos feature
queryClient.removeQueries({ queryKey: todoKeys.all });
// 🚀 invalidate all the lists
queryClient.invalidateQueries({ queryKey: todoKeys.lists() });
// 🙌 prefetch a single todo
queryClient.prefetchQueries({
queryKey: todoKeys.detail(id),
queryFn: () => fetchTodo(id),
});
queryFn 查询函数 查询函数实际上可以是任何返回 Promise 的函数。并应解析数据或抛出错误。
enabled 禁用\暂停查询
retry 查询重试次数
keepPreviousData 分页\滞后查询
const { isLoading, isError, error, data, isFetching, isPreviousData } =
useQuery({
queryKey: ["projects", page],
queryFn: () => fetchProjects(page),
keepPreviousData: true,
});
- initialData 初始查询数据\预填充数据 数据会持久保存在缓存中
const result = useQuery({
queryKey: ["todo", todoId],
queryFn: () => fetch("/todos"),
initialData: () => {
// 您可以从另一个查询的缓存结果中为查询提供初始数据
return queryClient.getQueryData(["todos"])?.find((d) => d.id === todoId);
},
// 更新初始数据
initialDataUpdatedAt: () =>
queryClient.getQueryState(["todos"])?.dataUpdatedAt,
});
- placeholderData 占位符查询数据 数据不会持久保存到缓存中
useMutation
mutationFn 突变函数
onMutate(variables) 突变触发
onError(error, variables, context) 突变错误
onSuccess(data, variables, context) 突变成功
onSettled(data, error, variables, context) 突变结束
// ✅ use an object for multiple variables
const mutation = useMutation({
mutationFn: ({ title, body }) => updateTodo(title, body),
});
mutation.mutate({ title: "hello", body: "world" });
userQueries 动态并行查询
使用它来动态地并行执行任意数量的查询
function App({ users }) {
const userQueries = useQueries({
queries: users.map((user) => {
return {
queryKey: ["user", user.id],
queryFn: () => fetchUserById(user.id),
};
}),
});
}
useQueryClient
- invalidateQueries 查询失效 指定要使哪些查询失效
queryClient.invalidateQueries({
queryKey: ["posts", id, "comments"],
exact: false,
});
- setQueryData 更新查询缓存 将指定的数据更新至查询缓存中
useMutation({
mutationFn: (newTitle) =>
axios
.patch(`/posts/${id}`, { title: newTitle })
.then((response) => response.data),
// 💡 response of the mutation is passed to onSuccess
onSuccess: (data) => {
// ✅ update detail view directly
queryClient.setQueryData(["posts", id], data);
},
});
等待失效完成
{
// 🎉 是否等待查询失效完成
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: ["posts", id, "comments"],
});
};
}
{
// 🚀 发后即忘 - 不会等待
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["posts", id, "comments"] });
};
}
- prefetchQuery 预取查询结果
const prefetchTodos = async () => {
// 此查询的结果将像普通查询一样被缓存
await queryClient.prefetchQuery({
queryKey: ["todos"],
queryFn: fetchTodos,
});
};
- cancelQueries 手动取消查询
queryClient.cancelQueries({ queryKey: ["todos"] });
useIsFetching 获取是否存在接口正在查询
使用示例
接口封装
import { useQuery, useMutation, QueryClient } from "@tanstack/react-query";
export const getZenCache = (params, options) => {
return useQuery(
["zen", params],
() => axios.get(`https://api.github.com/zen?id=${str}`),
{
select: (res) => res?.data || {}, // 防止对象取值不存在时的报错
...options,
}
);
};
组件中使用
const MutateCom = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (params) => new Promise((resolve) => resolve(params)),
onSuccess: (data, variables, context) => {
// 使查询失效,重新调用接口
queryClient.invalidateQueries({ queryKey: ["zen"] });
// queryClient.setQueryData(["zen"], { data: "dasdasd" });
},
});
};
const ApiCom = () => {
const query = getZenCache(id);
const editMutate = MutateCom();
const handleMutate = () => {
editMutate.mutate("666", {
onSuccess: (res) => {
console.log("success", res);
},
});
};
return (
<>
{query.isFetching && "loading..."}
{query.isError && query.error?.message}
{query?.data?.data}
<button onClick={handleMutate}>触发修改</button>
</>
);
};