Core Docs
Frontend

TanStack Query

Como o QueryClient é configurado e como usar devtools.

Provider

O QueryClient é criado em shared/components/providers/AppProviders.tsx, dentro de um client component, usando useState — isso evita o bug clássico de instanciar o client no escopo do módulo (o que causaria cache compartilhado entre requests/usuários diferentes em SSR):

'use client';
export function AppProviders({ children }: AppProvidersProps) {
  const [queryClient] = useState(() => new QueryClient());
  return (
    <QueryClientProvider client={queryClient}>
      {children}
      <Toaster richColors />
      {process.env.NODE_ENV === 'development' && <ReactQueryDevtools initialIsOpen={false} />}
    </QueryClientProvider>
  );
}

Defaults

O QueryClient não define defaultOptions — usa os padrões do TanStack Query v5 (staleTime: 0, refetchOnWindowFocus: true, retry: 3). Se uma tela estiver refazendo requisições com mais frequência do que o esperado, é por causa disso; ajuste caso a caso via opções do hook (useApiQuery) antes de mudar o default global.

Devtools

O botão flutuante do React Query Devtools aparece só em desenvolvimento (NODE_ENV === 'development'), nunca é incluído no bundle de produção.

Hooks de mutação

A maioria das mutações invalida a lista correspondente no onSuccess:

export const useForceDeleteCandidate = () => {
  const queryClient = useQueryClient();
  return useApiMutation<void, string>({
    mutationFn: forceDeleteCandidate,
    onSuccess: () => queryClient.invalidateQueries({ queryKey: candidateQueryKeys.lists() }),
  });
};

Evite queryClient.invalidateQueries() sem argumentos (invalida o cache inteiro) a menos que seja realmente essa a intenção — como no login, onde tudo pode ter mudado.

Invalidação mínima esperada

Quando a mutação altera uma entidade que também aparece em telas relacionadas, invalide todos os caches afetados pelo contrato, não só a tela atual. Exemplos:

  • Candidatura criada/removida/aprovada/desistida: invalidar applicationKeys.lists(), o detalhe da vaga (vacancyQueryKeys.detail(vacancyId)), listas de vagas e listas/detalhe do candidato.
  • Vaga aprovada/rejeitada/fechada/reaberta/editada: invalidar listas de vagas e vacancyQueryKeys.detail(vacancyId).
  • Candidato atualizado, especialmente restrição: invalidar listas de candidatos e candidateQueryKeys.detail(candidateId).

Esse padrão evita telas que só mostram o estado correto depois de atualizar com F5.

On this page