Deco
Pt

VTEX — hooks

useCart, useUser, useWishlist, useAutocomplete; legacy createUse* factories.

@decocms/apps/vtex/hooks provê hooks React para as interações de UI commerce mais comuns. Embrulham invoke com TanStack Query para que cache, refetching e mutações otimistas sejam pagos uma vez.

Import

 import {
  useCart,
  useUser,
  useWishlist,
  useAutocomplete,
} from "@decocms/apps/vtex/hooks"; 

useCart

 const {
  data: cart,
  isLoading,
  addItems,
  updateItems,
  removeItems,
  applyCoupon,
  changeRegion,
  isMutating,
} = useCart(); 

Estado do carrinho + mutações. Comportamento embutido:

  • Carregamento eager quando o hook monta (a menos que enabled: false ).
  • Atualizações otimistas em adicionar/remover/atualizar.
  • Auto-refetch após qualquer mutação para reconciliar com o server.
  • Refetch em focus (toggle) — desabilitado por default.

Padrão de uso em um botão “adicionar ao carrinho”:

 function AddToCartButton({ sku }: { sku: string }) {
  const { addItems, isMutating } = useCart();
  return (
    <button
      onClick={() => addItems([{ id: sku, quantity: 1 }])}
      disabled={isMutating}
    >
      {isMutating ? "Adicionando..." : "Adicionar ao carrinho"}
    </button>
  );
} 

useUser

 const {
  data: user,
  isLoading,
  signIn,
  signOut,
  signUp,
} = useUser(); 

Estado de auth + ações.

 function AccountWidget() {
  const { data: user, signOut } = useUser();
  if (!user) return <SignInLink />;
  return <span>Olá, {user.firstName} <button onClick={signOut}>Sair</button></span>;
} 

useWishlist

 const {
  data: wishlist,
  isLoading,
  add,
  remove,
  toggle,
  has,
} = useWishlist(); 

has(productId) devolve booleano sincronamente do estado em cache. toggle(productId) adiciona ou remove de acordo.

useAutocomplete

Para o input do header de busca:

 const { data, isLoading } = useAutocomplete(query, { enabled: query.length >= 2 }); 

Devolve { products: Product[]; suggestions: string[] } .

useAutocomplete é debounced internamente (200ms) — chame em todo keystroke; ele é safe.

Por que esses hooks?

Em v1, lojas frequentemente reimplementavam useCart no zero porque o context provider do Preact era escasso. v2 traz o hook plataforma-canônico, então toda loja tem o mesmo comportamento de cache e a mesma forma de mutação otimista de graça.

Se sua loja v1 customizou useCart (e.g. para mostrar loading states diferentes), porte essa lógica como wrapper:

 import { useCart as useCartBase } from "@decocms/apps/vtex/hooks";

export function useCart() {
  const cart = useCartBase();
  return {
    ...cart,
    isLoadingFirstTime: cart.isLoading && !cart.data,
  };
} 

Legacy: factories createUse*

@decocms/apps/vtex/hooks/legacy ainda exporta:

 import { createUseCart, createUseUser } from "@decocms/apps/vtex/hooks/legacy"; 

Eram a forma de extensibilidade no v1 (embrulhar o hook com transformação custom). Mantidas para compat de migração; prefira embrulhar os hooks novos diretamente.

TanStack Query por baixo

Todo hook usa um query key específico:

Hook Query key
useCart ["vtex", "cart"]
useUser ["vtex", "user"]
useWishlist ["vtex", "wishlist"]
useAutocomplete ["vtex", "autocomplete", query]

Use as keys para invalidar manualmente:

 import { useQueryClient } from "@tanstack/react-query";

const qc = useQueryClient();
qc.invalidateQueries({ queryKey: ["vtex", "cart"] }); 

Útil quando uma mutação fora do hook (e.g. submit de form) deve refletir no carrinho.

SSR e hidratação

Hooks chamam invoke que posta para /deco/invoke . No SSR, invoke é resolvido via RequestContext (sem round trip de rede). No client, vira fetch normal.

O resultado: hooks “funcionam” em ambos os ambientes, mas dados de SSR são tipicamente mais frescos. Por isso o cliente que se hidrata pode trocar — TanStack Query trata isso via revalidação default em mount.

Hidratação de carrinho zumbi

Bug clássico: SSR vê cookie do orderForm, render cart.items.length === 3 . Hidratação client-side fetcha sem o cookie (e.g. browsers terceiros bloqueando), render cart.items.length === 0 . UI “atualiza” para vazio.

Mitigação:

  • Defina staleTime: 30_000 em useCart para mudança de UI ser bloqueada na primeira hidratação.
  • Em ambientes server-render-known-different, vire o hook com enabled: false e oba via useState na hidratação inicial.

@decocms/apps/vtex/middleware/cookies cuida da maioria dos casos automaticamente — veja VTEX gotchas.

Veja também

Found an error or want to improve this page?

Edit this page