TanStack Query com Vue.js: O Gerenciador de Estado Assíncrono Definitivo

Se você já desenvolveu uma aplicação Vue.js de verdade, sabe que lidar com dados vindos de APIs é um dos maiores desafios do front-end. Loading, cache, refetch, sincronização entre componentes, invalidação… No fim, acabamos escrevendo dezenas de linhas de código repetitivo para algo que deveria ser simples. É justamente nesse…

Se você já desenvolveu uma aplicação Vue.js de verdade, sabe que lidar com dados vindos de APIs é um dos maiores desafios do front-end. Loading, cache, refetch, sincronização entre componentes, invalidação… No fim, acabamos escrevendo dezenas de linhas de código repetitivo para algo que deveria ser simples. É justamente nesse cenário que entra o TanStack Query, uma biblioteca que se tornou referência absoluta no gerenciamento de estado assíncrono e que possui um adaptador oficial e poderoso para o Vue.js.

O que é o TanStack Query?

O TanStack Query (anteriormente conhecido como Vue Query, na versão Vue) é frequentemente descrito como a “biblioteca de data-fetching que faltava” para aplicações web. Em termos mais técnicos, ele cuida do fetching, caching, sincronização e atualização do estado de servidor de forma transparente, deixando seu código declarativo e enxuto.

O ponto-chave para entender o valor da biblioteca é a diferença entre client state e server state. Soluções como Pinia e Vuex são excelentes para o estado do cliente (estado de UI, formulários, preferências do usuário), mas o estado do servidor tem características próprias:

  • É persistido remotamente, em um lugar que você não controla.
  • Exige APIs assíncronas para leitura e atualização.
  • Tem propriedade compartilhada — outras pessoas podem alterá-lo sem você saber.
  • Pode ficar “desatualizado” (stale) facilmente.

O TanStack Query resolve esses problemas de forma elegante, eliminando boa parte da complexidade que normalmente seria escrita à mão.

Por que usar TanStack Query no Vue.js?

  • Cache automático e inteligente: requisições iguais não são feitas duas vezes desnecessariamente.
  • Deduplicação de requisições: se vários componentes pedem o mesmo dado ao mesmo tempo, apenas uma chamada é feita.
  • Refetch em background: os dados são atualizados silenciosamente quando ficam stale ou quando a janela volta ao foco.
  • Estados prontos: isPending, isError, isSuccess, isFetching e muitos outros já vêm prontos.
  • Mutations e invalidação: atualizações de dados ficam consistentes em toda a aplicação.
  • DevTools dedicadas: uma extensão visual para inspecionar todas as queries em tempo real.
  • Suporte oficial ao Vue 2.6, 2.7 e Vue 3, além de integração com Nuxt 3.

Instalação no projeto Vue

A instalação é simples via NPM (ou seu gerenciador favorito):

npm install @tanstack/vue-query

Em seguida, registramos o plugin na inicialização da aplicação, normalmente no arquivo main.ts ou main.js:

import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import App from './App.vue'

const app = createApp(App)

app.use(VueQueryPlugin)
app.mount('#app')

Pronto: a partir daí, qualquer componente da aplicação pode usar os composables do TanStack Query.

Os três conceitos essenciais

Para começar com o TanStack Query, basta entender três conceitos centrais: Queries, Mutations e Query Invalidation. Vamos a um exemplo prático com a Composition API e <script setup>.

1. Queries — buscando dados

Uma query é uma busca de dados identificada por uma queryKey única. Veja como buscar uma lista de tarefas:

<script setup>
import { useQuery } from '@tanstack/vue-query'

const fetchTodos = async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos')
  return res.json()
}

const { isPending, isError, data, error } = useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
})
</script>

<template>
  <span v-if="isPending">Carregando...</span>
  <span v-else-if="isError">Erro: {{ error.message }}</span>
  <ul v-else>
    <li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
  </ul>
</template>

Observe como o código é declarativo: nada de onMounted, ref(true) para loading, try/catch manual. Tudo isso é gerenciado pela própria biblioteca.

2. Mutations — alterando dados

Enquanto queries são para leitura, mutations servem para criar, atualizar ou apagar dados. Combinadas com a invalidação, elas mantêm o cache sempre em sincronia.

<script setup>
import { useQueryClient, useMutation } from '@tanstack/vue-query'

const queryClient = useQueryClient()

const postTodo = async (novoTodo) => {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos', {
    method: 'POST',
    body: JSON.stringify(novoTodo),
  })
  return res.json()
}

const mutation = useMutation({
  mutationFn: postTodo,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
})

function adicionarTarefa() {
  mutation.mutate({
    id: Date.now(),
    title: 'Lavar a roupa',
  })
}
</script>

<template>
  <button @click="adicionarTarefa">Adicionar tarefa</button>
</template>

3. Query Invalidation — mantendo tudo em sincronia

O método invalidateQueries avisa ao TanStack Query: “ei, esses dados não são mais confiáveis, busque de novo”. Isso garante que qualquer componente exibindo aqueles dados seja atualizado automaticamente, sem precisarmos de eventos globais ou stores manuais.

Recursos avançados que vale conhecer

  • Paginated & Infinite Queries: suporte nativo para paginação e scroll infinito com useInfiniteQuery.
  • Dependent Queries: permita que uma query só rode depois que outra tiver dados.
  • Optimistic Updates: atualize a UI imediatamente, antes mesmo da resposta do servidor.
  • Prefetching: carregue dados antes do usuário precisar deles para uma experiência instantânea.
  • SSR & Nuxt: integração completa com renderização no servidor.
  • Polling e Refetch on Focus: mantenha os dados sempre frescos com configuração mínima.
  • Suspense: aproveite o Suspense do Vue 3 para um controle ainda mais granular de loading states.

Substitui o Pinia ou o Vuex?

Essa é uma das dúvidas mais comuns — e a resposta é: não, eles se complementam. O TanStack Query é especialista em server state, enquanto Pinia e Vuex continuam ideais para client state (tema da interface, autenticação local, formulários complexos, etc.). Na prática, muitos projetos passam a usar bem menos Pinia depois de adotar o TanStack Query, porque grande parte do estado global era, na verdade, cache de API disfarçado.

DevTools: seu novo melhor amigo

O TanStack Query oferece DevTools dedicadas que mostram em tempo real todas as queries ativas, seus estados, dados em cache e configurações. É um divisor de águas para debugar problemas de sincronização e entender o que está acontecendo na sua aplicação. Basta instalar e plugar:

npm install @tanstack/vue-query-devtools
<script setup>
import { VueQueryDevtools } from '@tanstack/vue-query-devtools'
</script>

<template>
  <RouterView />
  <VueQueryDevtools />
</template>

Conclusão

O TanStack Query mudou a forma como o ecossistema front-end lida com estado assíncrono — e no Vue.js não é diferente. Ele substitui dezenas de linhas de código frágil por uma API declarativa, com cache inteligente, sincronização automática e ferramentas de debug excelentes. Se você ainda escreve onMounted com fetch e ref para tudo, está na hora de experimentar. Comece pequeno, troque uma única tela do seu projeto, e em pouco tempo vai se perguntar como vivia sem essa biblioteca.

Para se aprofundar, vale visitar a documentação oficial em tanstack.com/query/latest, onde existem guias completos, exemplos para Vue 2, Vue 3 e Nuxt 3, além de receitas avançadas para casos reais.

0 Comentário