Skip to content

08 — React Query: Cache, staleTime e refetch

Pergunta: o tempo de mount sobra de rede ou de decisão de refetch? Onde a cache está sendo subutilizada (refetch desnecessário) e onde está sendo agressiva demais (dados stale demais)?

Contexto

src/routes.tsx:34-35 define o default global:

ts
staleTime: 5 * 60 * 1000   // 5 min
gcTime: 30 * 60 * 1000     // 30 min

Significa: por padrão toda query é considerada fresca por 5 min, sem refetch em remount. Bom default.

Evidência

ClusterHooksstaleTimeObservação
Default globalroutes.tsx5 minAplica em qualquer useQuery sem override
Admin FinanceirouseAdminFinanceiro.ts:175..27610s–60sCoerente (dados de pagamento em movimento)
Health/CronuseAdminHealthCheck.ts:11530sCoerente
Inscrições / Videos / Batch-inituseInscricoesOlimpiada.ts:33, useVideosCoord.ts:1055 minRedundante com global — verificar se é intencional
Realtime-backeduseFeatureLocksRealtime.ts, useFeatureLocks.ts(sem override)OK quando realtime invalida cache

Gap 1 — refetchOnWindowFocus / refetchOnMount

Não há override desses no global. Default do React Query 5 é refetchOnWindowFocus: true e refetchOnMount: 'always'. Combinado com staleTime: 5min o efeito é:

  • ✅ Mount com dados frescos não refetch (bom).
  • ❌ Mount com dados stale (>5min) refetch — comum quando o coord deixa a aba aberta e volta.
  • ❌ Toda volta de foco da janela refetch — em telas pesadas isso é o waterfall percebido.

Gap 2 — keepPreviousData ausente em listas paginadas

Quando virar paginação real no servidor (F1), obrigatório placeholderData: keepPreviousData. Sem isso, a tabela some/skeleton entre páginas e o usuário percebe "lentidão" mesmo com TTFB de 200ms.

Buscar: nenhum hook em src/hooks/ usa keepPreviousData ou placeholderData hoje.

Gap 3 — Invalidação ampla demais

invalidateQueries(['resultados']) invalida todas as variações (todas as escolas, todos os filtros). Em sessões multi-escola isso refaz queries inúteis. SSOT existente (mem://architecture/query-key-context-isolation) exige escola_id na chave — verificar adesão em todos os invalidateQueries do Resultados.

Hipóteses a validar

  • H1: Refetch em refetchOnWindowFocus é responsável por boa parte do "ele demorou de novo" que o usuário relata em segunda navegação.
  • H2: A ausência de placeholderData vai tornar a paginação servidor (F1) percebida como pior do que é.
  • H3: Invalidações estouram cache de outras escolas em sessão multi-perfil.

Próximas etapas (auditoria, não fix)

  • Listar todos os invalidateQueries de mutação em resultados/* e cruzar com a query-key real.
  • Decidir no SSOT (99): refetchOnWindowFocus: false por padrão + opt-in nos hooks que precisam (saldo financeiro, presença).
  • Reservar placeholderData: keepPreviousData como obrigatório em qualquer hook paginado servidor.