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 components
import { preload } 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
A abordagem recomendada em React Server Components (RSC) é iniciar a busca com preload e passar os dados retornados para a árvore de componentes do cliente por meio da opção cacheData do <SWRConfig>:
import { preload, SWRConfig } from 'swr'
export default async function Layout({ children }: { children: React.ReactNode }) {
const cacheData = {
...preload('/api/user', fetchUserFromAPI),
...preload('/api/posts', fetchPostsFromAPI),
}
return (
<SWRConfig value={{ cacheData }}>
{children}
</SWRConfig>
)
}As duas chamadas a preload iniciam a busca imediatamente, portanto as requisições são executadas em paralelo sem serem aguardadas no layout.
Em React Server Components, as promises dentro de cacheData podem atravessar a fronteira "use client", e o SWR as resolve automaticamente durante o Server-Side Rendering:
'use client'
import useSWR from 'swr'
export default function Page() {
// O SWR resolve os dados pré-carregados pelo Server Component.
// 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>
)
}O SWR usa o resultado carregado no servidor para a renderização inicial. No cliente, ele assume o controle e continua com o comportamento normal de revalidação.
Com preload e cacheData, a busca começa o mais cedo possível no servidor. Apenas os limites de UI que consomem os dados, como a fronteira Suspense mais próxima ou o layout do Next.js, sã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.
Como cacheData funciona
Este recurso requer o SWR 2.5.0-beta.1 ou posterior e atualmente é experimental.
Em um Server Component, preload(key, fetcher) inicia a busca imediatamente e retorna um objeto CacheData com escopo da requisição. Passe esse objeto para a opção cacheData do SWRConfig:
import { preload, SWRConfig } from 'swr'
import { User } from './user'
const getUser = () => fetchUserFromDatabase()
export default function Page() {
const cacheData = preload('/api/user', getUser)
return (
<SWRConfig value={{ cacheData }}>
<User />
</SWRConfig>
)
}O componente cliente usa a mesma chave com seu fetcher habitual do lado do cliente:
'use client'
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then(res => res.json())
export function User() {
const { data } = useSWR('/api/user', fetcher)
return <h1>{data?.name}</h1>
}O SWR usa o resultado carregado no servidor para a renderização inicial, grava-o no cache do cliente durante a hidratação e evita uma requisição inicial duplicada no cliente. As revalidações posteriores continuam usando o fetcher do cliente.
Cada chamada a preload retorna um novo objeto. Combine os objetos para pré-carregar várias chaves sem aguardá-las:
const cacheData = {
...preload('/api/user', getUser),
...preload('/api/posts', getPosts),
}preload serializa automaticamente chaves complexas do SWR. A opção cacheData é compatível apenas com SWRConfig; ela não pode ser passada diretamente para useSWR.
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 cacheData de SWRConfig para colocar os dados obtidos no servidor no cache de todos os hooks SWR dentro desse limite.
Por exemplo, com o getStaticProps:
export async function getStaticProps () {
// `getStaticProps` é executado no lado do servidor.
const article = await getArticleFromAPI()
return {
props: {
cacheData: {
'/api/article': article
}
}
}
}
function Article() {
// `data` está disponível por meio do `cacheData` fornecido pelo servidor.
const { data } = useSWR('/api/article', fetcher)
return <h1>{data.title}</h1>
}
export default function Page({ cacheData }) {
// Hooks SWR dentro do limites do `SWRConfig` usarão esses valores.
return (
<SWRConfig value={{ cacheData }}>
<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 renderiza os dados pré-gerados e os hidrata no cache do cliente sem duplicar a requisição inicial. Eventos de revalidação posteriores continuam usando o fetcher do cliente.
Chaves Complexas
useSWR pode ser usado com chaves dos tipos array e function. Ao criar cacheData manualmente, serialize essas chaves com unstable_serialize.
import useSWR, { unstable_serialize } from 'swr'
export async function getStaticProps () {
const article = await getArticleFromAPI(1)
return {
props: {
cacheData: {
// 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({ cacheData }) {
return (
<SWRConfig value={{ cacheData }}>
<Article />
</SWRConfig>
)
}