Skip to main content

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 loading e error state 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

RecursoDescrição
Cache automáticoArmazena resultados de fetch por chave (queryKey)
Revalidação inteligenteRefaz requisições ao reconectar, focar aba, ou invalidar
Sincronização automáticaQuando múltiplos componentes usam a mesma query
Evita requisições duplicadasApenas uma requisição por queryKey ativa
Refetch por tempoRequisições automáticas baseadas em staleTime
Devtools úteisInspeção e debug visual do cache/query/mutation
SSR, Suspense, Infinite Scroll, PaginaçãoSuporte 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 queryKey descritivos e com escopo bem definido
  • Use staleTime adequado para reduzir requisições desnecessárias
  • Prefira invalidateQueries a refetch manual
  • Evite misturar useEffect + axios sem 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