TanStack Query (React Query) | TanStack | React
- TanStack Query (React Query) | TanStack | React
📘 O que é?
info
-
Primeira explicação:
- TanStack Query (anteriormente React Query) é uma biblioteca para gerenciamento de estado do servidor em aplicações React. Ela trata de requisições HTTP assíncronas, cache, sincronização e consistência de dados entre a UI e a fonte de dados (geralmente uma API REST ou GraphQL).
-
Segunda explicação:
- O TanStack Query é uma biblioteca responsável por gerenciar estado assíncrono vindo do servidor dentro da aplicação frontend. Ele não substitui o React state nem um gerenciador global tradicional; ele resolve problemas específicos relacionados a dados remotos.
Diferentemente do Redux, Recoil ou Zustand, que lidam com o estado da interface, o TanStack Query foca no estado remoto (server state) — que é:
- Assíncrono
- Compartilhado
- Derivado de uma fonte externa
- Geralmente imutável pelo cliente (a menos que por mutations)
🚨 Problemas que ele resolve
Sem React Query, os devs geralmente:
- Fazem fetch manual com
useEffect+axios/fetch - Precisam de
loadingeerrorstate manuais - Implementam cache de forma rudimentar ou inexistente
- Sofrem com inconsistências de dados
- Fazem refetch com lógica duplicada
- Criam soluções ad-hoc para invalidação de dados e otimização
✅ Benefícios do React Query
| Recurso | Descrição |
|---|---|
| Cache automático | Armazena resultados de fetch por chave (queryKey) |
| Revalidação inteligente | Refaz requisições ao reconectar, focar aba, ou invalidar |
| Sincronização automática | Quando múltiplos componentes usam a mesma query |
| Evita requisições duplicadas | Apenas uma requisição por queryKey ativa |
| Refetch por tempo | Requisições automáticas baseadas em staleTime |
| Devtools úteis | Inspeção e debug visual do cache/query/mutation |
| SSR, Suspense, Infinite Scroll, Paginação | Suporte nativo |
🔧 Instalação e Setup
npm install @tanstack/react-query
Configuração básica no App
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<MyApp />
</QueryClientProvider>
);
}
🔍 Fazendo uma Query (GET)
Hook: useQuery
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
function useUsers() {
return useQuery({
queryKey: ['users'], // chave única para caching
queryFn: async () => {
const { data } = await axios.get('/api/users');
return data;
},
staleTime: 1000 * 60, // dados são "frescos" por 60s
cacheTime: 1000 * 300, // dados são mantidos no cache por 5min
refetchOnWindowFocus: true,
});
}
Uso em componente
function UsersList() {
const { data, isLoading, isError, error } = useUsers();
if (isLoading) return <p>Carregando...</p>;
if (isError) return <p>Erro: {error.message}</p>;
return (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
✍️ Fazendo Mutations (POST, PUT, DELETE)
Hook: useMutation
info
No TanStack Query, uma mutation é usada para modificar dados no servidor, ou seja: Enviar dados do cliente para o servidor usando métodos como POST, PUT, PATCH ou DELETE.
useQuery = fetching → busca e cache de dados (estado do servidor → cliente)
useMutation = writing → alteração de dados (cliente → servidor)
import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';
function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (newUser) => axios.post('/api/users', newUser),
onSuccess: () => {
// Invalida a query para refazer o fetch com dados atualizados
queryClient.invalidateQueries({ queryKey: ['users'] });
},
onError: (error) => {
console.error('Erro ao criar usuário', error);
}
});
}
Uso:
function CreateUserButton() {
const createUser = useCreateUser();
const handleClick = () => {
createUser.mutate({ name: 'Novo Usuário' });
};
return <button onClick={handleClick}>Criar usuário</button>;
}
🧠 Explicação dos parâmetros importantes
queryKey
- Uma chave única (array ou string) que identifica o cache.
- Usada para diferenciar os dados no cache.
queryKey: ['user', userId]
staleTime
- Tempo em milissegundos durante o qual os dados são considerados "frescos".
- Enquanto fresco, React Query não faz refetch ao focar a aba ou montar o componente.
cacheTime
- Tempo após o qual os dados inativos (sem uso em nenhum componente) são removidos da memória.
enabled
- Permite controlar condicionalmente o fetch.
useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
enabled: !!userId, // só executa se houver um userId
});
🔁 Refetch manual
const { refetch } = useQuery(...);
<button onClick={() => refetch()}>Atualizar</button>
🧩 Devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
Permite:
- Visualizar todas as queries/mutations
- Inspecionar dados, status, erros
- Invalidar ou refazer manualmente
📚 Avançado
Queries dependentes
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
enabled: !!userId
});
const { data: posts } = useQuery({
queryKey: ['posts', user?.id],
queryFn: () => fetchPostsByUser(user.id),
enabled: !!user?.id
});
Infinite Queries
Para infinite scroll:
import { useInfiniteQuery } from '@tanstack/react-query';
const fetchPage = async ({ pageParam = 1 }) => {
const { data } = await axios.get(`/api/posts?page=${pageParam}`);
return data;
};
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: ['posts'],
queryFn: fetchPage,
getNextPageParam: (lastPage, pages) => {
return lastPage.nextPage ?? false;
},
});
🧪 Boas práticas
- Separe lógica de dados em hooks (
useUsers,usePosts, etc) - Use
queryKeydescritivos e com escopo bem definido - Use
staleTimeadequado para reduzir requisições desnecessárias - Prefira
invalidateQueriesa refetch manual - Evite misturar
useEffect+axiossem necessidade
❗Atenção
- React Query não gerencia estado local da UI
- Cache em memória: se recarregar a página, o cache some (a menos que use persistência)
- Mutations não têm cache automático – é responsabilidade sua invalidar ou atualizar queries
Diferenças entre Next.js (SSR/ISR/cache) e Tanstack Query
Documentação sobre quando usar cada um: 🔗 Clique aqui