与 Next.js 一同使用
App Router
Server Components
在 Next.js App Router 中,所有的组件都被默认视为 React Server Components (RSC) 。在 RSC 中您可以从 SWR 引入 SWRConfig 和序列化 Key API
import { unstable_serialize } from 'swr' // ✅ 在 Server components 中可用
import { unstable_serialize as infinite_unstable_serialize } from 'swr/infinite' // ✅ 在 Server components 中可用
import { SWRConfig } from 'swr' // ✅ 在 Server components 中可用您不能从 SWR 引入 hook API ,因为它们在 RSC 中不可用。
import useSWR from 'swr' // ❌ 在 Server components 中不可用
import useSWRInfinite from 'swr/infinite' // ❌ 在 Server components 中不可用
import useSWRMutation from 'swr/mutation' // ❌ 在 Server components 中不可用Client Components
您可以直接用 'use client' 标记您的组件或者从 Client Components 引入 SWR ,两种方法都允许您使用 SWR 提供的客户端数据获取 Hooks。
'use client'
import useSWR from 'swr'
export default function Page() {
const { data } = useSWR('/api/user', fetcher)
return <h1>{data.name}</h1>
}在服务器组件中预获取数据
类似于 带有默认数据的预渲染 模式,使用 React Server Components (RSC) 你可以更进一步。
您可以在服务器端 启动 数据预获取,并通过 <SWRConfig> provider 的 fallback 选项将 promise 传递给客户端组件树:
import { SWRConfig } from 'swr'
export default async function Layout({ children }: { children: React.ReactNode }) {
// 在服务器端启动数据获取
const userPromise = fetchUserFromAPI()
const postsPromise = fetchPostsFromAPI()
return (
<SWRConfig
value={{
fallback: {
// 将 promise 传递给客户端组件
'/api/user': userPromise,
'/api/posts': postsPromise,
},
}}
>
{children}
</SWRConfig>
)
}这两个数据获取函数调用 fetchUserFromAPI() 和 fetchPostsFromAPI() 将在服务器端并行执行,因为我们不会立即 await 它们。
在 React Server Components 中,您可以跨越 "use client" 边界传递 promise,SWR 将在服务端渲染期间自动解析它们:
'use client'
import useSWR from 'swr'
export default function Page() {
// SWR 将解析从服务器组件传递的 promise
// 在 SSR 和客户端 hydration 期间,'user' 和 'posts' 都已准备就绪
const { data: user } = useSWR('/api/user', fetcher)
const { data: posts } = useSWR('/api/posts', fetcher)
return (
<div>
<h1>{user.name}'s Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
)
}然后,在客户端 SWR 将接管并保持与平常一样的行为。
通过将 promise 从服务器组件传递到客户端组件,数据获取可以尽可能早地在服务器端启动。并且只有实际使用数据的 UI 边界(最近的 Suspense 边界或 Next.js layout)才会在流式 SSR 期间被阻塞。
要在应用程序中逐步采用此预获取模式,您可以启用 strictServerPrefetchWarning 选项。这将在控制台中显示警告消息,当某个 key 没有提供预填充数据时,帮助您识别哪些数据获取调用可以从服务器端预获取中受益。
客户端数据获取
如果您的页面包含一些频繁更新的数据,而您并不需要预渲染这些数据,SWR 将非常适用并且并不需要特殊的配置:只需要引入 useSWR 然后在任何需要使用数据的组件中使用这个 Hook
以下是它的工作方式:
- 首先,立即在没有数据的情况下展示页面。您可以显示缺失数据的加载状况。
- 然后,在客户端获取数据,并在数据准备好时展示它们.
例如,这个方法在用户仪表盘页面上工作得很好。因为仪表板是不公开、用户特定的页面,与 SEO 无关并且页面不需要预渲染。数据频繁更新,需要在请求时获取。
带有默认数据的预渲染
如果页面需要预渲染,Next.js 支持 两种预渲染方式: 静态生成 (SSG) and 服务端渲染 (SSR).
通过使用 SWR, 您可以为了 SEO 预渲染页面, 并同时在客户端享受缓存、重新验证、焦点追踪、定时重新获取等特性。
您可以使用 SWRConfig 的 fallback 选项来将预获取的数据作为所有 SWR Hook 的初始值。
使用 getStaticProps 的例子:
export async function getStaticProps () {
// `getStaticProps` 在服务端执行
const article = await getArticleFromAPI()
return {
props: {
fallback: {
'/api/article': article
}
}
}
}
function Article() {
// `data` 将始终可用,因为其处于 `fallback` 列表中
const { data } = useSWR('/api/article', fetcher)
return <h1>{data.title}</h1>
}
export default function Page({ fallback }) {
// 在 `SWRConfig` 标签内的 SWR hooks 将使用这些值
return (
<SWRConfig value={{ fallback }}>
<Article />
</SWRConfig>
)
}该页面仍然是预先生成,SEO 友好的,并且能够快速反应。然而该页面在客户端侧仍然完全由 SWR 驱动。数据仍然是动态的,且可以自动更新。
Article 组件将先渲染预先生成的数据,并且在页面水合完成后将再次获取最新数据以保持数据最新
复杂关键字
useSWR 可以与 array 和 function 类型的 key 一同使用. 若要通过这些类型的 key 使用预先获取的数据,需要用 unstable_serialize 序列化 fallback key.
import useSWR, { unstable_serialize } from 'swr'
export async function getStaticProps () {
const article = await getArticleFromAPI(1)
return {
props: {
fallback: {
// unstable_serialize() array style key
[unstable_serialize(['api', 'article', 1])]: article,
}
}
}
}
function Article() {
// using an array style key.
const { data } = useSWR(['api', 'article', 1], fetcher)
return <h1>{data.title}</h1>
}
export default function Page({ fallback }) {
return (
<SWRConfig value={{ fallback }}>
<Article />
</SWRConfig>
)
}