axios-hooks、react-query(现 @tanstack/react-query)和 swr 都是用于在 React 应用中管理服务端状态的工具,但它们的定位和能力范围有所不同。axios-hooks 专注于为 Axios 请求提供简单的 Hook 封装,适合轻量级需求。react-query 是一个功能强大的异步状态管理库,提供复杂的缓存、背景更新和突变管理。swr 由 Vercel 维护,主打轻量级和“先返回旧数据再重新验证”的策略,适合快速集成和简单场景。
在 React 开发生态中,管理服务端数据一直是个核心挑战。axios-hooks、react-query 和 swr 都试图解决这个问题,但它们的设计哲学和适用场景截然不同。axios-hooks 更像是一个请求库的包装器,而 react-query 和 swr 则是完整的异步状态管理器。让我们从实际工程角度深入对比。
axios-hooks 直接绑定 Axios 配置,返回请求状态。
// axios-hooks: 绑定 Axios 配置
import useAxios from 'axios-hooks';
function UserProfile() {
const { data, loading, error } = useAxios('/users/123');
if (loading) return <div>加载中...</div>;
return <div>{data.name}</div>;
}
react-query 使用唯一的查询键(Query Key)来管理状态。
// react-query: 使用查询键
import { useQuery } from '@tanstack/react-query';
function UserProfile() {
const { data, isLoading, error } = useQuery({
queryKey: ['user', 123],
queryFn: () => fetch('/users/123').then(res => res.json())
});
if (isLoading) return <div>加载中...</div>;
return <div>{data.name}</div>;
}
swr 使用 URL 或键作为缓存标识,强调简洁。
// swr: 使用键或 URL
import useSWR from 'swr';
function UserProfile() {
const { data, isLoading, error } = useSWR('/users/123', fetcher);
if (isLoading) return <div>加载中...</div>;
return <div>{data.name}</div>;
}
axios-hooks 默认不处理缓存。
// axios-hooks: 无内置缓存
// 每次渲染都会触发新请求,除非手动配置缓存实例
const { data } = useAxios('/users/123');
react-query 提供精细的缓存控制。
staleTime(数据保鲜期)和 cacheTime(缓存存活期)。// react-query: 精细缓存控制
useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
staleTime: 1000 * 60 * 5, // 5 分钟内数据视为新鲜
refetchOnWindowFocus: true // 窗口聚焦时重新验证
});
swr 主打 Stale-While-Revalidate 策略。
// swr: 自动后台重新验证
useSWR('/users', fetcher, {
revalidateOnFocus: true, // 默认开启
dedupingInterval: 2000 // 2 秒内重复请求去重
});
axios-hooks 通常手动处理突变。
// axios-hooks: 手动管理突变
const updateUser = async (id, data) => {
setLoading(true);
try {
await axios.put(`/users/${id}`, data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
react-query 提供专用的 useMutation。
// react-query: 专用 Mutation Hook
const mutation = useMutation({
mutationFn: updateUser,
onSuccess: () => {
queryClient.invalidateQueries(['users']); // 自动更新列表
}
});
swr 提供 mutate 函数。
// swr: 使用 mutate 函数
import useSWR, { mutate } from 'swr';
const handleUpdate = async (data) => {
mutate('/users', updateUser(data), {
optimisticData: { ...oldData, ...data }
});
};
axios-hooks 维护频率较低。
// axios-hooks: 社区资源较少
// 遇到问题可能需要自己阅读源码解决
react-query 由 TanStack 维护,非常活跃。
// react-query: 强大的 DevTools
// 可在浏览器中直观查看缓存状态和查询详情
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
swr 由 Vercel 维护,稳定可靠。
// swr: 与 Next.js 无缝集成
// 特别适合部署在 Vercel 平台的项目
| 特性 | axios-hooks | react-query | swr |
|---|---|---|---|
| 定位 | Axios 请求封装 | 异步状态管理 | 轻量数据获取 |
| 缓存机制 | 无(需手动) | 强大且可配置 | 自动 Stale-While-Revalidate |
| 突变管理 | 手动实现 | useMutation 专用 Hook | mutate 函数 |
| 请求库依赖 | 强制 Axios | 无关(Fetch/Axios 均可) | 无关(Fetch/Axios 均可) |
| 开发者工具 | 无 | 官方 DevTools | 基础支持 |
| 维护状态 | 低活跃度 | 极高活跃度 | 高活跃度 |
axios-hooks 就像一把专用螺丝刀 🪛 — 如果你只需要拧 Axios 这一种螺丝,它很简单。但在现代复杂应用中,它缺乏管理数据生命周期的能力。仅建议在维护旧项目或极简单的内部工具中使用。
react-query 就像一套完整的工程机床 🏭 — 功能强大,可控制每一个细节。适合需要高度可靠性、复杂缓存策略和团队协作的大型应用。它是目前企业级 React 开发的事实标准。
swr 就像一把瑞士军刀 🇨🇭 — 轻便、够用、开箱即用。适合初创项目、内容型网站或希望减少配置负担的团队。如果你已经在用 Next.js,它通常是默认选择。
最终建议:对于大多数新启动的专业前端项目,优先选择 react-query 以获得长期的可维护性和功能扩展性。如果项目极度追求轻量且逻辑简单,swr 是优秀的备选。尽量避免在新架构中依赖 axios-hooks,除非你有非常特殊的 Axios 绑定需求。
如果你追求轻量级集成,喜欢简单的 API 设计,或者项目部署在 Vercel 生态中,swr 非常合适。它适合内容展示型网站、中小型应用,或者当你希望快速实现数据获取而不想配置复杂的缓存策略时。
如果你需要企业级的数据管理功能,包括强大的缓存控制、背景同步、乐观更新和复杂的突变流程,react-query 是最佳选择。它适合复杂的管理后台、仪表盘或数据密集型应用,且拥有完善的开发者工具和生态系统支持。
如果你的项目已经深度绑定 Axios 且只需要简单的请求状态包装,不需要复杂的缓存策略,可以选择 axios-hooks。但需注意其社区活跃度相对较低,适合小型工具类项目或遗留系统维护。对于新的大型项目,建议评估更通用的状态管理方案。
SWR is a React Hooks library for data fetching.
The name “SWR” is derived from stale-while-revalidate, a cache invalidation strategy popularized by HTTP RFC 5861.
SWR first returns the data from cache (stale), then sends the request (revalidate), and finally comes with the up-to-date data again.
With just one hook, you can significantly simplify the data fetching logic in your project. And it also covered in all aspects of speed, correctness, and stability to help you build better experiences:
...and a lot more.
With SWR, components will get a stream of data updates constantly and automatically. Thus, the UI will be always fast and reactive.
View full documentation and examples on swr.vercel.app.
import useSWR from 'swr'
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (isLoading) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
In this example, the React Hook useSWR accepts a key and a fetcher function.
The key is a unique identifier of the request, normally the URL of the API. And the fetcher accepts
key as its parameter and returns the data asynchronously.
useSWR also returns 3 values: data, isLoading and error. When the request (fetcher) is not yet finished,
data will be undefined and isLoading will be true. When we get a response, it sets data and error based on the result
of fetcher, isLoading to false and rerenders the component.
Note that fetcher can be any asynchronous function, you can use your favourite data-fetching
library to handle that part.
View full documentation and examples on swr.vercel.app.
This library is created by the team behind Next.js, with contributions from our community:
Thanks to Ryan Chen for providing the awesome swr npm package name!
The MIT License.