SWR 是什么?
SWR 是一个由 Vercel(Next.js 开发公司)推出的 React 数据获取库,用于高效获取、缓存和自动同步远程数据。
SWR 代表:
- Stale(过期)
- While(在)
- Revalidate(重新验证)
SWR 的核心思想是:
先返回缓存数据(如果有),然后发送请求获取最新数据,并自动更新 UI。
SWR 适用于:
- 数据请求和缓存管理(Client-Side Fetching)
- 自动重新验证数据(如窗口聚焦、重新连接)
- SSR & ISR 支持(与 Next.js 兼容)
SWR 的主要功能
- 自动缓存和重新验证(避免重复请求)
- 支持窗口聚焦时自动刷新数据
- 支持离线恢复(重新连接后自动同步)
- 支持数据依赖(可基于一个请求的结果触发另一个请求)
- 支持乐观 UI 更新(Optimistic UI)
如何使用 SWR?
1. 安装 SWR
npm install swr
2. 在 React 组件中使用 SWR
import useSWR from 'swr'
// 定义请求方法
const fetcher = (url: string) => fetch(url).then(res => res.json())
export default function Profile() {
// SWR 请求数据
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return <div>获取数据失败</div>
if (isLoading) return <div>加载中...</div>
return <div>用户名称: {data.name}</div>
}
解释:
useSWR('/api/user', fetcher)
:向/api/user
发送 GET 请求,并返回数据data
:存储服务器返回的数据error
:存储请求失败的错误信息isLoading
:指示是否仍在加载数据
SWR 的高级用法
1. 全局配置 SWR
可以使用 SWRConfig
提供全局配置,比如全局 fetcher
、刷新策略等:
import { SWRConfig } from 'swr'
export default function MyApp({ Component, pageProps }) {
return (
<SWRConfig value={{ fetcher: (url) => fetch(url).then(res => res.json()) }}>
<Component {...pageProps} />
</SWRConfig>
)
}
这样,所有 useSWR()
的请求都会自动使用这个 fetcher
。
明确对比 全局配置 vs. 局部配置的区别。
例子 1:没有 <SWRConfig>
,每个请求都要手动写参数
如果没有 <SWRConfig>
,我们必须在每个 useSWR()
里单独写 shouldRetryOnError: false
和 revalidateOnFocus: false
:
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then(res => res.json())
function UserProfile() {
const { data, error } = useSWR('/api/user', fetcher, {
shouldRetryOnError: false,
revalidateOnFocus: false
})
if (error) return <div>加载失败</div>
if (!data) return <div>加载中...</div>
return <div>用户名: {data.name}</div>
}
function UserPosts() {
const { data, error } = useSWR('/api/posts', fetcher, {
shouldRetryOnError: false,
revalidateOnFocus: false
})
if (error) return <div>加载失败</div>
if (!data) return <div>加载中...</div>
return (
<ul>
{data.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
)
}
export default function App() {
return (
<div>
<UserProfile />
<UserPosts />
</div>
)
}
缺点:
shouldRetryOnError: false
和revalidateOnFocus: false
在每个请求中都要重复写,代码冗余,维护麻烦。
例子 2:使用 <SWRConfig>
统一管理
使用 <SWRConfig>
,所有 useSWR()
自动继承默认配置:
import { SWRConfig } from 'swr'
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then(res => res.json())
function UserProfile() {
const { data, error } = useSWR('/api/user')
if (error) return <div>加载失败</div>
if (!data) return <div>加载中...</div>
return <div>用户名: {data.name}</div>
}
function UserPosts() {
const { data, error } = useSWR('/api/posts')
if (error) return <div>加载失败</div>
if (!data) return <div>加载中...</div>
return (
<ul>
{data.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
)
}
export default function App() {
return (
<SWRConfig value={{
fetcher, // 全局 fetcher
shouldRetryOnError: false,
revalidateOnFocus: false
}}>
<UserProfile />
<UserPosts />
</SWRConfig>
)
}
优势:
UserProfile
和UserPosts
不用再手动传shouldRetryOnError
和revalidateOnFocus
,代码更简洁。- 统一管理 SWR 配置,方便维护。
2. 依赖另一个数据
当一个 API 请求需要依赖另一个 API 的结果时:
function UserProfile() {
const { data: user } = useSWR('/api/user', fetcher)
const { data: projects } = useSWR(user ? `/api/projects?user=${user.id}` : null, fetcher)
if (!user) return <div>加载用户信息...</div>
if (!projects) return <div>加载项目列表...</div>
return (
<div>
<h1>{user.name} 的项目</h1>
<ul>
{projects.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
</div>
)
}
关键点:
useSWR(user ? '/api/projects?user=' + user.id : null, fetcher)
- 只有
user
数据加载完成后,才会发起/api/projects
请求
- 只有
3. 自动刷新数据
SWR 允许设置自动刷新时间,比如每隔 5 秒刷新一次:
const { data } = useSWR('/api/user', fetcher, { refreshInterval: 5000 })
4. 手动触发数据重新验证
import useSWR, { mutate } from 'swr'
const { data } = useSWR('/api/user', fetcher)
// 重新获取最新数据
const refreshData = () => {
mutate('/api/user')
}
<button onClick={refreshData}>刷新用户数据</button>
mutate()
可以手动触发 SWR 重新获取数据,而无需用户刷新页面。
SWR vs React Query
特性 | SWR | React Query |
---|---|---|
提供缓存 | ✅ | ✅ |
自动重新验证 | ✅ | ✅ |
窗口聚焦刷新 | ✅ | ✅ |
手动触发更新 | ✅ mutate() |
✅ queryClient.invalidateQueries() |
SSR/ISR 支持 | ✅(适用于 Next.js) | ✅(需要额外配置) |
适用于简单数据请求 | ✅ | ✅ |
适用于复杂数据(分页、表单、请求依赖等) | ⚠️(需要自定义) | ✅ |
选择建议:
- SWR 适合 Next.js,用于简单数据获取(如用户信息、配置等)。
- React Query 适合更复杂的应用,如分页、表单提交、乐观更新等。
总结
- SWR 是一个 React 的数据获取库,基于“Stale-While-Revalidate”策略。
- 提供高效的缓存、自动重新获取数据,支持窗口聚焦刷新等功能。
- 适用于 Next.js 和客户端数据获取,提升用户体验。