Gerenciando estado remoto com React Query
Eduardo Rabelo
Posted on May 5, 2021
React é uma das bibliotecas de front-end mais apreciadas pela comunidade de desenvolvedores. Junto com o React, os termos como DOM Virtual, Componentes Funcionais, Gestão de Estado e Componentes de Ordem-Superior (Higher-Order Components). Entre esses termos, a Gestão de Estado desempenha um papel vital.
O gerenciamento de estado é um dos principais fatores que precisam ser considerados antes de iniciar um projeto React. Os desenvolvedores usam padrões e bibliotecas famosas como Flux, Redux e Mobx para gerenciar o estado em React. No entanto, eles adicionam complexidade e código boilerplate ao seus aplicativos.
Neste artigo, vamos discutir como o React Query aborda o problema mencionado acima, criando um pequeno aplicativo pokemon e mergulhando em seus conceitos-chave.
Dica: Compartilhe seus componentes reutilizáveis entre projetos usando Bit (veja no GitHub). O Bit simplifica o compartilhamento, a documentação e a organização de componentes independentes de qualquer projeto.
Podemos usá-lo para maximizar a reutilização de código, colaboração em componentes independentes e criar aplicativos escaláveis.
O Bit suporta Node, TypeScript, React, Vue, Angular e muito mais.
O que é React Query?
React Query é uma das ferramentas de gerenciamento de estado que tem uma abordagem diferente do Flux, Redux e Mobx. Ele apresenta os principais conceitos de Estado-do-Cliente e Estado-do-Servidor. Isso torna o React Query uma das melhores bibliotecas para gerenciar estado, já que todos os outros padrões de gerenciamento de estado tratam apenas do estado do cliente e acham difícil lidar com o estado do servidor que precisa ser buscado, ouvido ou inscrito.
Além de lidar com o estado do servidor, ele funciona incrivelmente bem, sem precisar de configurações customizadas, e pode ser personalizado de acordo com o seu gosto conforme o crescimento do seu aplicativo.
Vamos ver isso na prática usando alguns exemplos.
Instalando o React Query
Em primeiro lugar, vamos instalar a React QUery dentro de um projeto React:
npm install react-query react-query-devtools axios --save
Ou:
yarn add react-query react-query-devtools axios
Configurando Ferramentas de Desenvolvimento
O React Query também tem suas próprias ferramentas de desenvolvimento, que nos ajudam a visualizar o funcionamento interno do React Query. Vamos configurar as ferramentas de desenvolvimento do React Query no arquivo App.js:
import { ReactQueryDevtools } from "react-query-devtools";
function App() {
return (
<>
{/* Os outros componentes da nossa aplicação */}
<ReactQueryDevtools initialIsOpen={false} />
</>
);
}
Quando configuramos as ferramentas de desenvolvimento do React Query, você pode ver o logotipo do React Query na parte inferior esquerda do seu aplicativo, assim:
O devtools nos ajuda a ver como o fluxo de dados acontece dentro do aplicativo, assim como Redux Devtools. Isso realmente ajuda a reduzir o tempo de depuração do aplicativo.
Assim como o GraphQL, o React Query também se baseia em conceitos básicos semelhantes, como
- Query
- Mutações
- Invalidação de Query
Buscando Pokémons usando Query
Neste exemplo, vamos usar a PokéApi. Começaremos com useQuery, que recebe uma chave única e uma função responsável por buscar dados:
import React from "react";
import axios from "axios";
import { useQuery } from "react-query";
import Card from "./Card";
const fetchPokemons = async () => {
const { data } = await axios.get("https://pokeapi.co/api/v2/pokemon/?limit=50");
return data;
};
function Main() {
const { data, status } = useQuery("pokemons", fetchPokemons);
const PokemonCard = (pokemons) => {
return pokemons.results.map((pokemon) => {
return <Card key={pokemon.name} name={pokemon.name}></Card>;
});
};
return (
<div>
{status === "loading" && <div>Loading...</div>}
{status === "error" && <div>Error fetching pokemons</div>}
{status === "success" && <div>{PokemonCard(data)}</div>}
</div>
);
}
export default Main;
O código acima irá renderizar uma UI como abaixo:
Cache no React Query
Como você pode ver, useQuery retorna os dados e o status que podem ser usados para exibir componentes de "Carregando...", mensagens de erro e os dados reais. Por padrão, React Query só solicitará dados quando eles estiverem desatualizados ou antigos.
O React Query armazena os dados em cache para não renderizar os componentes, a menos que haja uma alteração. Também podemos usar alguma configuração especial com useQuery para atualizar os dados em segundo plano.
const {data, status} = useQuery ("pokemons", fetchPokemons, {staleTime: 5000, cacheTime: 10});
A configuração acima fará com que o React Query busque dados a cada 5 segundos em segundo plano. Também podemos definir um cacheTime
e um retryTime
que define o tempo que o navegador deve manter o cache e o número de tentativas em que ele deve buscar dados.
Redefinindo o Cache com Invalidação de Query
O React Query buscará dados assim que os dados / cache estiverem desatualizados. Isso acontece quando o staleTime
padrão é passado. Você também pode invalidar o cache de maneira programática para que o React Query atualize os dados.
Para fazer isso, use queryCache
. É uma instância utilitária que contém muitas funções que podem ser usadas para manipular ainda mais as Query e invalidar o cache.
queryCache.invalidateQueries("pokemons");
Variáveis no React Query
Também podemos passar variáveis para a query. Para isso, precisamos transmiti-los como um array.
const { data, status } = useQuery(["pokemons",75], fetchPokemons);
O primeiro elemento será a chave e o resto dos elementos são variáveis. Para usar a variável, vamos fazer algumas modificações em nossa função fetchPokemons
.
const fetchPokemons = async (key,limit) => {
const { data } = await axios.get(`https://pokeapi.co/api/v2/pokemon/?limit=${limit}`);
return data;
};
Brincando com Mutações
As mutações são normalmente usadas para criar / atualizar / excluir dados ou executar efeitos colaterais do lado do servidor. O React Query fornece o hook useMutation
para realizar mutações. Vamos criar uma mutação para criar um pokémon:
import React from "react";
import { useQuery } from "react-query";
function Pokemon() {
const [name, setName] = useState("");
const [mutateCreate, { error, reset }] = useMutation(
(text) => axios.post("/api/data", { text }),
{
onSuccess: () => {
setName("");
},
}
);
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
mutateCreate(name);
}}
>
{error && <h5 onClick={() => reset()}>{error}</h5>}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<br />
<button type="submit">Create Pokemon</button>
</form>
</div>
);
}
export default Pokemon;
Neste exemplo, quando adicionamos um novo nome de Pokémon e clicamos no botão Criar Pokémon , ele fará a mutação e irá buscar os dados. Se a mutação falhar, o erro será exibido.
O erro e o estado dos dados podem ser eliminados usando a função reset
, que reinicializará a mutação. A função onSuccess
pode ser usada para limpar o estado da entrada ou do nome.
Uma mutação tem mais propriedades como onSuccess
, isIdle
, isLoading
, isError
, isSuccess
. Eles podem ser usados para lidar com erros e exibir informações relevantes para diferentes estados da mutação.
Conclusão
O React Query é uma das melhores maneiras de buscar, armazenar em cache e atualizar dados remotos. Precisamos apenas dizer à biblioteca onde você precisa buscar os dados, e ela tratará do cache, das atualizações em segundo plano e da atualização dos dados sem nenhum código ou configuração extra.
Ele também fornece alguns hooks e eventos para mutação e query para lidar com erros e outros estados dos efeitos colaterais, o que remove a necessidade de usar hooks como useState
e useEffect
e os substitui por algumas linhas com React Query.
Créditos
- React Query — An Underrated State Management Tool, escrito originalmente por Tharaka Romesh.
Posted on May 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.