Usando com Next.js
App Router
Server Components
No App Router do Next.js, todos os componentes são React Server Components (RSC) por padrão. Você pode importar SWRConfig e as APIs de serialização de chave do SWR em RSCs.
import { unstable_serialize } from 'swr' // ✅ Disponível em server components
import { unstable_serialize as infinite_unstable_serialize } from 'swr/infinite' // ✅ Disponível em server components
import { SWRConfig } from 'swr' // ✅ Disponível em server componentsVocê não pode importar hook APIs do SWR, pois elas não estão disponíveis em RSCs.
import useSWR from 'swr' // ❌ Isso não está disponível em components
import useSWRInfinite from 'swr/infinite' // ❌ Isso não está disponível em components
import useSWRMutation from 'swr/mutation' // ❌ Isso não está disponível em componentsClient Components
Você pode marcar seus componentes com a diretiva 'use client' ou importar o SWR de componentes do cliente, ambos os caminhos permitirão que você use os hooks de busca de dados do cliente SWR.
'use client'
import useSWR from 'swr'
export default function Page() {
const { data } = useSWR('/api/user', fetcher)
return <h1>{data.name}</h1>
}Buscar Dados Antecipadamente em Server Components
Similar ao padrão de pré-renderização com dados padrão, com React Server Components (RSC) você pode ir ainda mais longe.
Você pode iniciar a busca antecipada de dados no lado do servidor e passar a promise para a árvore de componentes do cliente através da opção fallback do provider <SWRConfig>:
import { SWRConfig } from 'swr'
export default async function Layout({ children }: { children: React.ReactNode }) {
// Inicie a busca de dados no lado do servidor.
const userPromise = fetchUserFromAPI()
const postsPromise = fetchPostsFromAPI()
return (
<SWRConfig
value={{
fallback: {
// Passe as promises para os componentes do cliente.
'/api/user': userPromise,
'/api/posts': postsPromise,
},
}}
>
{children}
</SWRConfig>
)
}As duas chamadas de função de busca de dados fetchUserFromAPI() e fetchPostsFromAPI() serão executadas em paralelo no lado do servidor porque não as aguardamos imediatamente.
Em React Server Components, você pode passar promises através da fronteira "use client", e o SWR irá resolvê-las automaticamente durante o Server-Side Rendering:
'use client'
import useSWR from 'swr'
export default function Page() {
// O SWR resolverá a promise passada dos componentes do servidor.
// Tanto `user` quanto `posts` estarão prontos durante SSR e hidratação do cliente.
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>
)
}Então, no lado do cliente, o SWR assumirá o controle e manterá o comportamento normal.
Ao passar promises dos Server Components para Client Components, a busca de dados pode ser iniciada o mais cedo possível no lado do servidor. E apenas os limites de UI (fronteira Suspense mais próxima ou layout Next.js) que realmente consomem os dados serão bloqueados durante o SSR de streaming.
Para adotar incrementalmente este padrão de pré-busca em sua aplicação, você pode habilitar a opção strictServerPrefetchWarning. Isso mostrará uma mensagem de aviso no console quando uma chave não tem dados pré-preenchidos fornecidos, ajudando você a identificar quais chamadas de busca de dados poderiam se beneficiar da pré-busca do lado do servidor.
Obtendo dados em Client-side
Se a sua página contém dados que atualizam frequentemente, e você não precisa pré-renderizar os dados, o SWR é perfeito e não precisa de configuração especial: apenas importe o useSWR e use o hook dentro de qualquer componente que use os dados.
Funciona assim:
- Primeiro, imediatamente mostre a página sem dados. Você pode mostrar estados de carregamento para dados que estão faltando.
- Então, busque os dados no lado do cliente e exiba-os quando estiver pronto.
Essa estratégia funciona bem para páginas de dashboard de usuário, por exemplo. Como a página do dashboard é uma página privada e específica do usuário, o SEO não é relevante e a página não precisa ser pré-renderizada. Os dados são atualizados com frequência, o que requer a busca de dados no momento da solicitação.
Pré-rendedrizando com dados padrão
Se a página precisa ser pré-renderizada, o Next.js suporta 2 formas de pré-renderização: Geração Estática (SSG) e Renderização Server-side (SSR).
Junto com o SWR, você pode pré-renderizar a página para SEO e também ter recursos como cache, revalidação, rastreamento de foco, refetching em intervalo no lado do cliente.
Você pode usar a opção fallback de SWRConfig para passar os dados pré-buscados como o valor inicial de todos os hooks SWR.
Por exemplo, com o getStaticProps:
export async function getStaticProps () {
// `getStaticProps` é executado no lado do servidor.
const article = await getArticleFromAPI()
return {
props: {
fallback: {
'/api/article': article
}
}
}
}
function Article() {
// `data` estará sempre disponível, pois está em `fallback`.
const { data } = useSWR('/api/article', fetcher)
return <h1>{data.title}</h1>
}
export default function Page({ fallback }) {
// Hooks SWR dentro do limites do `SWRConfig` usarão esses valores.
return (
<SWRConfig value={{ fallback }}>
<Article />
</SWRConfig>
)
}A página ainda é pré-renderizada. É amigável para SEO, rápida para responder, mas também totalmente alimentada pelo SWR no lado do cliente. Os dados podem ser dinâmicos e atualizados automaticamente ao longo do tempo.
O componente Article irá renderizar os dados pré-gerados primeiro e, após a página ser hidratada, ele buscará novamente os dados mais recentes para mantê-los atualizados.
Chaves Complexas
useSWR podem ser usadas com chaves que são do tipo array ou function. Utilizar dados pré-obtidos com esses tipos de chaves requer serializar as chaves fallback usando o unstable_serialize.
import useSWR, { unstable_serialize } from 'swr'
export async function getStaticProps () {
const article = await getArticleFromAPI(1)
return {
props: {
fallback: {
// chave de lista usando unstable_serialize()
[unstable_serialize(['api', 'article', 1])]: article,
}
}
}
}
function Article() {
// usando uma chave de estilo de array.
const { data } = useSWR(['api', 'article', 1], fetcher)
return <h1>{data.title}</h1>
}
export default function Page({ fallback }) {
return (
<SWRConfig value={{ fallback }}>
<Article />
</SWRConfig>
)
}