Skip to content
Documentação
Comece a Usar

Comece a Usar

Instalação

Dentro do diretório do seu projeto React, execute o seguinte:

pnpm add swr

Início Rápido

Para APIs RESTful normais com dados JSON, primeiro você precisa criar uma função fetcher, que é apenas um wrapper do nativo fetch:

const fetcher = (...args) => fetch(...args).then(res => res.json())
💡

Se você quer usar APIs GraphQL ou outras bibliotecas como Axios, você pode criar sua própria função fetcher. Veja mais exemplos clicando aqui.

Então você pode importar useSWR e começar a usá-lo em qualquer componente funcional:

import useSWR from 'swr'
 
function Profile () {
  const { data, error, isLoading } = useSWR('/api/user/123', fetcher)
 
  if (error) return <div>falhou ao carregar</div>
  if (isLoading) return <div>carregando...</div>
 
  // renderizar dados
  return <div>olá {data.name}!</div>
}

Normalmente, existem 3 possíveis estados de uma requisição: "loading", "ready", ou "error". Você pode usar o valor de data, error e isLoading para determinar o estado atual da requisição, e retornar a interface correspondente.

Torne-o Reutilizável

Quando construir uma aplicação web, você pode precisar reutilizar os dados em vários lugares da interface do usuário. É muito fácil criar reutilizações de dados em cima do SWR:

function useUser (id) {
  const { data, error, isLoading } = useSWR(`/api/user/${id}`, fetcher)
 
  return {
    user: data,
    isLoading,
    isError: error
  }
}

E usá-lo em seus componentes:

function Avatar ({ id }) {
  const { user, isLoading, isError } = useUser(id)
 
  if (isLoading) return <Spinner />
  if (isError) return <Error />
  return <img src={user.avatar} />
}

Adotando esse padrão, você pode esquecer sobre o fetching de dados no modo imperativo: inicie a requisição, atualize o estado de carregamento e retorne o resultado final. Ao invés, seu código é mais declarativo: você só precisa especificar o que dados é usado pelo componente.

Exemplo

Num exemplo real, o nosso site mostra uma barra de navegação e o conteúdo, ambos dependem de user:

Tradicionalmente, nós carregamos dados uma vez usando useEffect no componente principal, e passamos os dados para os componentes filhos via props (note que nós não tratamos o estado de erro por agora).

// componente da página
 
function Page () {
  const [user, setUser] = useState(null)
 
  // obtendo os dados data
  useEffect(() => {
    fetch('/api/user')
      .then(res => res.json())
      .then(data => setUser(data))
  }, [])
 
  // estado de carregamento (loading) global
  if (!user) return <Spinner/>
 
  return <div>
    <Navbar user={user} />
    <Content user={user} />
  </div>
}
 
// componentes filho
 
function Navbar ({ user }) {
  return <div>
    ...
    <Avatar user={user} />
  </div>
}
 
function Content ({ user }) {
  return <h1>Bem vindo de volta, {user.name}</h1>
}
 
function Avatar ({ user }) {
  return <img src={user.avatar} alt={user.name} />
}

Normalmente, nós precisamos manter todos os dados de carregamento no componente principal e adicionar props para todos os componentes. O código fica mais difícil de manter se adicionarmos mais dependências de dados à página.

Apesar que possamos evitar passar props para componentes filhos, isto é, usar Context (opens in a new tab), ainda há o problema do conteúdo dinâmico: componentes dentro da página podem ser dinâmicos, e o componente principal pode não saber quais dados serão necessários por seus componentes filhos.

SWR resolve o problema perfeitamente. Com o hook useUser, o código pode ser refatorado para:

// componente page
 
function Page () {
  return <div>
    <Navbar />
    <Content />
  </div>
}
 
// componentes filho
 
function Navbar () {
  return <div>
    ...
    <Avatar />
  </div>
}
 
function Content () {
  const { user, isLoading } = useUser()
  if (isLoading) return <Spinner />
  return <h1>Bem-vindo de volta, {user.name}</h1>
}
 
function Avatar () {
  const { user, isLoading } = useUser()
  if (isLoading) return <Spinner />
  return <img src={user.avatar} alt={user.name} />
}

Os dados agora estão vinculados aos componentes que precisam dos dados, e todos os componentes são independentes uns dos outros. Todos os componentes pai não precisam saber nada sobre os dados ou transmitir dados. Eles apenas renderizam. O código é muito mais simples e fácil de manter agora.

O mais bonito é que haverá apenas 1 solicitação enviada para a API, pois eles usam a mesma chave SWR e a solicitação é duplicada, armazenada em cache e compartilhada automaticamente.

Além disso, o aplicativo agora tem a capacidade de buscar novamente os dados ao focar do usuário ou reconexão de rede! Isso significa que, quando o laptop do usuário sair do modo de suspensão ou alternar entre as guias do navegador, os dados serão atualizados automaticamente.