blense.
InícioFrontendProgramaçãoIANotíciasGuiasCheatsheetsSobre

Tecnologia decodificada, sempre.

Uma leitura curada sobre IA, produto e a cultura por trás do código. Sem ruído, sem hype.

blense.

Tecnologia com foco. Histórias sobre o que a inovação realmente muda.

Seções

FrontendInteligência ArtificialProgramação & DevNotícias Tech

Blense

SobreRSSPolítica de privacidadeTermosCookies
© 2026 Blense · blense.fun
Guias & Tutoriais

TanStack Query: Como Eliminar o Gerenciamento Manual de Estado de Servidor no React

Aprenda a usar o TanStack Query para gerenciar cache, sincronização e estados de servidor em aplicações React de forma simples e eficiente.

Gpor Genildo Souza20 de mar.7 min de leitura
TanStack Query: Como Eliminar o Gerenciamento Manual de Estado de Servidor no React

Aprenda a usar o TanStack Query para gerenciar buscas de dados, cache, atualizações e sincronização em aplicações React, simplificando o gerenciamento de estado de servidor.


O que vamos aprender
  • 1- O que é TanStack Query e por que usar
  • 2- Configuração básica do QueryClient
  • 3- Busca de dados com `useQuery`
  • 4- Gerenciamento de estados (carregamento, erro, sucesso)
  • 5- Atualização de dados com `useMutation`
  • 6- Cache e invalidação de queries
  • 7- Configurações avançadas (staleTime, cacheTime)
  • 8- Paginação e busca infinita
  • 9- Boas práticas e padrões recomendados

Introdução ao TanStack Query

Cansado de gerenciar manualmente estados de carregamento, tratar erros de rede e implementar lógica complexa de cache em cada componente? O TanStack Query, anteriormente conhecido como React Query, elimina essa carga operacional ao automatizar a busca, sincronização e atualização de dados, permitindo que você foque inteiramente na lógica da sua aplicação React.

Analogia: Imagine que seu aplicativo React é um restaurante. TanStack Query é como o gerente de cozinha que:

Analogia do TanStack Query como gerente de cozinha Usa Gerencia Verifica Solicita Aplicativo React O restaurante GERENTE TanStack Query Gerente de cozinha GERENTE Cache (pratos disponíveis) GERENTE staleTime (ingredientes frescos) GERENTE Refetch (solicita novos ingredientes)
Analogia do TanStack Query como gerente de cozinha
  • Sabe quais pratos estão disponíveis (cache)

  • Verifica se os ingredientes estão frescos (staleTime)

  • Solicita novos ingredientes quando necessário (refetch)

  • Lida com pedidos especiais (mutations)

  • Notifica quando algo está esgotado (erro)

Conceito Fundamental 1: Configuração Básica

Primeiro, precisamos configurar o QueryClient e envolver nossa aplicação:

JSX
// src/main.jsximport React from 'react';import ReactDOM from 'react-dom/client';import { QueryClient, QueryClientProvider } from '@tanstack/react-query';import App from './App';// Cria uma instância do QueryClientconst queryClient = new QueryClient({  defaultOptions: {    queries: {      staleTime: 1000 * 60 * 5, // 5 minutos      refetchOnWindowFocus: false,    },  },});ReactDOM.createRoot(document.getElementById('root')).render(  <React.StrictMode>    <QueryClientProvider client={queryClient}>      <App />    </QueryClientProvider>  </React.StrictMode>);

Explicação:

  • QueryClient gerencia o cache e as operações

  • QueryClientProvider disponibiliza o client para todos os componentes

  • defaultOptions define configurações globais

Dica: Mantenha uma única instância do QueryClient para toda a aplicação.

Conceito Fundamental 2: Buscando Dados com useQuery

O hook useQuery é usado para buscar e sincronizar dados:

JSX
// src/components/UserList.jsximport { useQuery } from '@tanstack/react-query';const fetchUsers = async () => {  const response = await fetch('https://api.example.com/users');  if (!response.ok) {    throw new Error('Falha ao buscar usuários');  }  return response.json();};export const UserList = () => {  const { data, error, isLoading, isError } = useQuery({    queryKey: ['users'], // Chave única para identificar esta query    queryFn: fetchUsers, // Função que busca os dados  });  if (isLoading) {    return <div>Carregando...</div>;  }  if (isError) {    return <div>Erro: {error.message}</div>;  }  return (    <div>      <h1>Usuários</h1>      <ul>        {data.map(user => (          <li key={user.id}>{user.name}</li>        ))}      </ul>    </div>  );};

Explicação:

  • queryKey: Identificador único para esta query (organiza o cache)

  • queryFn: Função assíncrona que retorna os dados ou lança erro

  • isLoading: Indica se a query está carregando pela primeira vez

  • isError: Indica se ocorreu um erro

  • error: Objeto de erro se isError for true

  • data: Os dados retornados pela query

Resultado esperado:

  • Inicialmente exibe "Carregando..."

  • Após a busca, exibe uma lista de usuários ou mensagem de erro

Conceito Fundamental 3: Atualizando Dados com useMutation

useMutation é usado para criar, atualizar ou deletar dados:

JSX
// src/components/AddUser.jsximport { useMutation, useQueryClient } from '@tanstack/react-query';const addUser = async (newUser) => {  const response = await fetch('https://api.example.com/users', {    method: 'POST',    headers: {      'Content-Type': 'application/json',    },    body: JSON.stringify(newUser),  });  if (!response.ok) {    throw new Error('Falha ao adicionar usuário');  }  return response.json();};export const AddUser = () => {  const queryClient = useQueryClient();  const [name, setName] = useState('');  const mutation = useMutation({    mutationFn: addUser,    onSuccess: () => {      // Invalida a query de usuários para forçar refetch      queryClient.invalidateQueries({ queryKey: ['users'] });    },  });  const handleSubmit = (e) => {    e.preventDefault();    mutation.mutate({ name });    setName('');  };  return (    <form onSubmit={handleSubmit}>      <input        type="text"        value={name}        onChange={(e) => setName(e.target.value)}        placeholder="Nome do usuário"      />      <button type="submit" disabled={mutation.isLoading}>        {mutation.isLoading ? 'Adicionando...' : 'Adicionar Usuário'}      </button>      {mutation.isError && <div>Erro: {mutation.error.message}</div>}    </form>  );};

Explicação:

  • useQueryClient: Acessa o cliente para invalidar queries

  • mutationFn: Função que executa a mutação

  • onSuccess: Callback executado quando a mutação é bem-sucedida

  • mutate: Função para acionar a mutação

  • isLoading: Indica se a mutação está em andamento

Conceito Avançado: Configurações de Query

TanStack Query oferece muitas configurações para controlar o comportamento:

JSX
const { data } = useQuery({  queryKey: ['posts'],  queryFn: fetchPosts,  // Dados são considerados frescos por 5 minutos  staleTime: 1000 * 60 * 5,  // Dados são mantidos no cache por 10 minutos após ficarem obsoletos  cacheTime: 1000 * 60 * 10,  // Refetch quando a janela ganhar foco  refetchOnWindowFocus: true,  // Refetch quando a conexão for restabelecida  refetchOnReconnect: true,  // Refetch quando a página for retomada  refetchOnMount: true,  // Busca em segundo plano (a cada 30 segundos)  refetchInterval: 1000 * 30,  // Desativa busca em segundo plano quando a aba estiver inativa  refetchIntervalInBackground: false,});

Exemplo Prático 1: Paginação

JSX
// src/components/PaginatedPosts.jsximport { useQuery } from '@tanstack/react-query';const fetchPosts = async (page = 1, limit = 10) => {  const response = await fetch(    `https://api.example.com/posts?page=${page}&limit=${limit}`  );  if (!response.ok) {    throw new Error('Falha ao buscar posts');  }  return response.json();};export const PaginatedPosts = () => {  const [page, setPage] = useState(1);  const { data, isLoading, isError } = useQuery({    queryKey: ['posts', page], // Inclui a página na chave    queryFn: () => fetchPosts(page),    keepPreviousData: true, // Mantém dados da página anterior  });  if (isLoading) return <div>Carregando...</div>;  if (isError) return <div>Erro ao carregar posts</div>;  return (    <div>      <h1>Posts</h1>      <ul>        {data.posts.map(post => (          <li key={post.id}>{post.title}</li>        ))}      </ul>      <div>        <button onClick={() => setPage(page - 1)} disabled={page === 1}>          Anterior        </button>        <span> Página {page} </span>        <button onClick={() => setPage(page + 1)}>          Próximo        </button>      </div>    </div>  );};

Exemplo Prático 2: Busca Infinita

JSX
// src/components/InfinitePosts.jsximport { useInfiniteQuery } from '@tanstack/react-query';const fetchPosts = async ({ pageParam = 1 }) => {  const response = await fetch(    `https://api.example.com/posts?page=${pageParam}`  );  if (!response.ok) {    throw new Error('Falha ao buscar posts');  }  return response.json();};export const InfinitePosts = () => {  const {    data,    fetchNextPage,    hasNextPage,    isFetchingNextPage,    status,  } = useInfiniteQuery({    queryKey: ['infinite-posts'],    queryFn: fetchPosts,    getNextPageParam: (lastPage) => lastPage.nextPage,    initialPageParam: 1,  });  if (status === 'loading') return <div>Carregando...</div>;  if (status === 'error') return <div>Erro ao carregar posts</div>;  return (    <div>      <h1>Posts Infinitos</h1>      <div>        {data.pages.map((page, i) => (          <div key={i}>            {page.posts.map(post => (              <div key={post.id}>{post.title}</div>            ))}          </div>        ))}      </div>      <button        onClick={() => fetchNextPage()}        disabled={!hasNextPage || isFetchingNextPage}      >        {isFetchingNextPage          ? 'Carregando mais...'          : hasNextPage          ? 'Carregar Mais'          : 'Nada mais para carregar'}      </button>    </div>  );};

Erros Comuns e Como Evitar

  1. Não invalidar queries após mutations

    • Problema: Os dados exibidos não refletem as alterações recentes

    • Solução: Use onSuccess em useMutation para invalidar queries relevantes

  2. Chaves de query inconsistentes

    • Problema: O mesmo endpoint com parâmetros diferentes é tratado como a mesma query

    • Solução: Inclua todos os parâmetros relevantes na queryKey

  3. Esquecer de tratar estados de erro

    • Problema: A aplicação quebra quando uma falha de rede ocorre

    • Solução: Sempre verifique isError e error em seus componentes

  4. Usar staleTime muito curto

    • Problema: Muitas requisições desnecessárias ao servidor

    • Solução: Ajuste o staleTime com base na frequência de atualização dos dados

⚠️
Erro Comum: Não Invalidar Queries Após Mutations

Quando você realiza uma mutation, os dados exibidos podem ficar desatualizados se as queries relacionadas não forem invalidadas.

Isso causa inconsistência na interface, mostrando informações que não refletem as alterações recentes.

A solução é usar o callback onSuccess do useMutation para invalidar as queries relevantes, garantindo que os dados sejam atualizados automaticamente.

Boas Práticas

  • Use chaves de query específicas e previsíveis

  • Mantenha as funções de busca puras e sem efeitos colaterais

  • Trate todos os estados possíveis (loading, error, success)

  • Configure staleTime e cacheTime apropriadamente para seu caso de uso

  • Use select para transformar dados no componente quando necessário

  • Prefira invalidar queries em vez de refetch manualmente

  • Documente suas chaves de query para facilitar a manutenção

Arsenal do dev de elite.
Linux sem decoreba: domine o terminal com lógica6 minAPI de IA Grátis em 2026: Use Llama, DeepSeek e Mistral Sem Pagar Nada (Guia Completo)17 minAstro: Arquitetura de Ilhas, Performance e Onde o Framework Realmente Se Encaixa41 minMicrofrontends com Angular e Nx: o que ninguém conta16 min

Para ir além

  • Documentação oficial do TanStack Query

Takeaway: TanStack Query simplifica drasticamente o gerenciamento de estado de servidor em React. Ao entender os conceitos fundamentais de queries, mutations e cache, você pode criar aplicações mais responsivas, resilientes e fáceis de manter. Comece com as configurações básicas e explore gradualmente os recursos avançados conforme suas necessidades crescem.

Continue explorando
Quer mais conteúdo assim?

Veja outros artigos na mesma linha e mantenha o ritmo.

Ver mais artigos
#JavaScript#TypeScript

Arsenal do dev de elite.

Linux sem decoreba: domine o terminal com lógica
Guias & Tutoriais

Linux sem decoreba: domine o terminal com lógica

A tela preta espera comandos, mas o Linux não é decoreba: é anatomia lógica. Do kernel ao prompt, quatro princípios tiram o medo do terminal.

Genildo Souza · 16 de jun. · 6 min
API de IA Grátis em 2026: Use Llama, DeepSeek e Mistral Sem Pagar Nada (Guia Completo)
Guias & Tutoriais

API de IA Grátis em 2026: Use Llama, DeepSeek e Mistral Sem Pagar Nada (Guia Completo)

A barreira de entrada para usar inteligência artificial de fronteira caiu para zero em 2026.

Genildo Souza · 27 de abr. · 17 min
Finalmente Entenda Bash/Linux Terminal: As Explicações Claras Que Você Merece
Guias & Tutoriais

Finalmente Entenda Bash/Linux Terminal: As Explicações Claras Que Você Merece

O terminal parece intimidador, mas o Bash possui atalhos poderosos. Aprenda a automatizar tarefas e simplificar comandos com estas dicas práticas.

Genildo Souza · 13 de dez. · 16 min
Neste artigo
  • Introdução ao TanStack Query
  • Conceito Fundamental 1: Configuração Básica
  • Conceito Fundamental 2: Buscando Dados com useQuery
  • Conceito Fundamental 3: Atualizando Dados com useMutation
  • Conceito Avançado: Configurações de Query
  • Exemplo Prático 1: Paginação
  • Exemplo Prático 2: Busca Infinita
  • Erros Comuns e Como Evitar
  • Boas Práticas
  • Para ir além