SWR 是一个由 Vercel(Next.js 开发公司)推出的 React 数据获取库,用于高效获取、缓存和自动同步远程数据。
SWR 代表:
SWR 的核心思想是:
先返回缓存数据(如果有),然后发送请求获取最新数据,并自动更新 UI。
SWR 适用于:
npm install 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
:指示是否仍在加载数据可以使用 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. 局部配置的区别。
<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
在每个请求中都要重复写,代码冗余,维护麻烦。<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
,代码更简洁。当一个 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
请求SWR 允许设置自动刷新时间,比如每隔 5 秒刷新一次:
const { data } = useSWR('/api/user', fetcher, { refreshInterval: 5000 })
import useSWR, { mutate } from 'swr'
const { data } = useSWR('/api/user', fetcher)
// 重新获取最新数据
const refreshData = () => {
mutate('/api/user')
}
<button onClick={refreshData}>刷新用户数据</button>
mutate()
可以手动触发 SWR 重新获取数据,而无需用户刷新页面。
特性 | SWR | React Query |
---|---|---|
提供缓存 | ✅ | ✅ |
自动重新验证 | ✅ | ✅ |
窗口聚焦刷新 | ✅ | ✅ |
手动触发更新 | ✅ mutate() |
✅ queryClient.invalidateQueries() |
SSR/ISR 支持 | ✅(适用于 Next.js) | ✅(需要额外配置) |
适用于简单数据请求 | ✅ | ✅ |
适用于复杂数据(分页、表单、请求依赖等) | ⚠️(需要自定义) | ✅ |
选择建议: