前言
最近参与新的项目了,发现项目居然使用了 @tanstack/react-query
,以前之后简单介绍过,今天再来详细上手使用下!

往期精彩推荐
- Node.js v24.6.0 新功能速览
- 原来在字节写代码就是这么朴实无华!
- Webpack 项目也可以引入大模型问答了!感谢 Rsdoctor 1.2 !
- 更多精彩文章欢迎关注我的公众号:萌萌哒草头将军
正文
@tanstack/react-query
是 TanStack 生态的一部分,专为 React、Vue 等框架设计,用于管理服务器状态和异步数据。
它无需全局状态库,就能处理数据获取、缓存、突变和同步,支持 TS/JS,并提供开发工具。
以下是 React Query 的详细使用过程
准备
bash
pnpm add @tanstack/react-query
然后在根入口处使用 Provider
!
js
import React from "react";
import {
QueryClient,
QueryClientProvider
} from "@tanstack/react-query";
import Layout from "@/Layout";
export default function App() {
// 创建 QueryClient 实例
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<Layout />
</QueryClientProvider>
);
}
useQuery 请求数据
useQuery
用于数据获取,支持自动缓存、重取和错误处理!
javascript
import React from "react";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
function fetchUser(userId: number) {
return axios.get(`https://jsonplaceholder.typicode.com/users/${userId}`).then(res => res.data);
}
function User({ userId }: { userId: number }) {
const { data, isLoading, isError, error, refetch } = useQuery({
queryKey: ["user", userId], // 缓存 key
queryFn: () => fetchUser(userId),
// 数据在缓存中保持 1 分钟为新鲜,不会重复请求
staleTime: 1000 * 60,
// 数据缓存 5 分钟
cacheTime: 1000 * 60 * 5,
// 请求失败自动重试 2 次
retry: 2,
onError: (err) => {
console.error("获取用户数据失败:", err);
}
});
if (isLoading) return <div>加载中...</div>;
if (isError) return <div>出错了: {(error as Error).message}</div>;
return (
<div>
<h2>{data.name}</h2>
<p>Email: {data.email}</p>
<button onClick={() => refetch()}>手动触发重取</button>
</div>
);
}
staleTime
的默认值为 0 ,也就是说立马失效,不会缓存!
2. 突变与更新(useMutation)
useMutation 用于数据更新,如 POST 请求,支持乐观更新和回滚。
javascript
import React, { useState } from "react";
import {
useQuery,
useMutation,
useQueryClient
} from "@tanstack/react-query";
import axios from "axios";
// 模拟获取待办列表
const fetchTodos = () => axios.get("/api/todos").then(res => res.data);
// 模拟添加待办
const addTodo = (text: string) => axios.post("/api/todos", { text }).then(res => res.data);
export function Todos() {
const queryClient = useQueryClient();
const [newText, setNewText] = useState("");
// 获取待办列表
const { data: todos = [] } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
// useMutation 用于新增待办
const mutation = useMutation({
mutationFn: addTodo,
// 乐观更新
onMutate: async (text: string) => {
await queryClient.cancelQueries({ queryKey: ["todos"] });
const previousTodos = queryClient.getQueryData<any[]>(["todos"]);
// 立即更新缓存,显示新增项
queryClient.setQueryData(["todos"], [...(previousTodos || []), { id: Date.now(), text }]);
return { previousTodos }; // 返回上下文,用于失败回滚
},
// 出错时回滚
onError: (_err, _variables, context: any) => {
if (context?.previousTodos) {
queryClient.setQueryData(["todos"], context.previousTodos);
}
},
// 成功后刷新缓存
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ["todos"] });
}
});
return (
<div>
<h2>待办列表</h2>
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
<input value={newText} onChange={e => setNewText(e.target.value)} placeholder="新增待办" />
<button onClick={() => mutation.mutate(newText)}>添加</button>
</div>
);
}
并行/依赖查询
并行查询时只需要写多个 useQuery 即可,
js
const userQuery = useQuery({
queryKey: ["user", userId],
queryFn: () => fetchUser(userId),
});
const postsQuery = useQuery({
queryKey: ["posts", userId],
queryFn: () => fetchPosts(userId),
});
如果需要依赖查询,则需要使用 enabled
属性!
js
const userQuery = useQuery({
queryKey: ["userByName", username],
queryFn: () => axios.get(`/api/users?username=${username}`).then(res => res.data),
});
const postsQuery = useQuery({
queryKey: ["posts", userQuery.data?.id],
queryFn: () => axios.get(`/api/users/${userQuery.data.id}/posts`).then(res => res.data),
// 只有当 userQuery 获取到 id 时才触发
enabled: !!userQuery.data?.id,
});
开发工具集成
开发时,可以搭配它的开发者工具,
js
import React from "react";
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import Layout from "@/Layout";
// 创建 QueryClient
const queryClient = new QueryClient();
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Layout />
<ReactQueryDevtools initialIsOpen={false} position="bottom-right" />
</QueryClientProvider>
);
}

点击打开控制面板,是这样的:

最后
@tanstack/react-query
解决了数据管理的痛点,通过 useQuery
和 useMutation
等钩子,让代码更简洁、更可靠。感兴趣的话感觉用它来优化你的项目吧!
今天的分享就这些了,感谢大家的阅读!如果文章中存在错误的地方欢迎指正!
往期精彩推荐
- Node.js v24.6.0 新功能速览
- 原来在字节写代码就是这么朴实无华!
- Webpack 项目也可以引入大模型问答了!感谢 Rsdoctor 1.2 !
- 更多精彩文章欢迎关注我的公众号:萌萌哒草头将军