跳到主要内容

React-Query基本使用

· 阅读需 5 分钟
chalk

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>
</>
);
};