VOOZH about

URL: https://dev.to/carlosorioli/sincronizando-zustand-com-vtex-orderform-no-react-native-3ab9

⇱ Sincronizando Zustand com VTEX OrderForm no React Native - DEV Community


Recentemente, precisei desenvolver uma integração de checkout VTEX dentro de um aplicativo React Native. O desafio era garantir que a experiência de compra fosse fluida, mantendo o estado do carrinho perfeitamente sincronizado entre o ambiente nativo do app e a finalização da compra na WebView.

Para resolver isso, utilizei o Zustand para o gerenciamento de estado global e a API de Checkout da VTEX para manipular o orderFormId.

A Arquitetura da Solução

A ideia central foi: o App gerencia os produtos e quantidades através de uma store leve Zustand e, antes de abrir o checkout, sincronizamos tudo com a VTEX via API.

1. Gerenciando o Carrinho com Zustand

A store armazena o orderFormId e persiste os dados para que o carrinho não se perca. Aqui, podemos escolher entre o AsyncStorage (padrão) ou o MMKV (para performance ultra-rápida).

import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MMKV } from 'react-native-mmkv';

// Opção com MMKV (Alta Performance)
const storage = new MMKV();
const mmkvStorage = {
 setItem: (name, value) => storage.set(name, value),
 getItem: (name) => storage.getString(name) ?? null,
 removeItem: (name) => storage.delete(name),
};

export const useCartStore = create(
 persist(
 (set) => ({
 orderFormId: null,
 items: [],
 setOrderFormId: (id) => set({ orderFormId: id }),
 addToCart: (item) => set((state) => ({ items: [...state.items, item] })),
 clearCart: () => set({ items: [], orderFormId: null }),
 }),
 {
 name: 'cart-storage',
 // Troque 'mmkvStorage' por 'AsyncStorage' se preferir o padrão
 storage: createJSONStorage(() => mmkvStorage), 
 }
 )
);

Para esse projeto, utilizei o MMKV pela velocidade de leitura/escrita, mas a estrutura funciona perfeitamente com AsyncStorage também.

2. Sincronizando com a API da VTEX

Antes de navegar para a tela de checkout, enviamos os itens para o orderForm específico. Isso evita disparar várias chamadas de rede desnecessárias durante a navegação.

const syncCartWithVtex = async (orderFormId, items) => {
 try {
 await fetch(`https://{ACCOUNT}.vtexcommercestable.com.br/api/checkout/pub/orderForm/${orderFormId}/items`, {
 method: 'POST',
 headers: { 'Content-Type': 'application/json' },
 body: JSON.stringify({
 orderItems: items.map(i => ({ id: i.id, quantity: i.quantity, seller: "1" }))
 }),
 });
 } catch (error) {
 console.error("Erro na sincronização:", error);
 }
};

DICA: A VTEX às vezes exige que o cabeçalho vtex-id-client-authtoken seja enviado se o usuário já estiver autenticado no app, para que o carrinho não fique como "anônimo"

3. O Checkout na WebView

A sacada foi é injetar o orderFormId na URL da WebView. Assim, o checkout da VTEX já abre com todos os itens que o usuário escolheu no app.

import { WebView } from 'react-native-webview';

const VtexCheckout = () => {
 const { orderFormId } = useCartStore();

 // URL que vincula a sessão ao carrinho do App
 const checkoutUrl = `https://www.sualoja.com.br/checkout/?orderFormId=${orderFormId}#/cart`;

 return (
 <WebView 
 source={{ uri: checkoutUrl }}
 sharedCookiesEnabled={true} //PARA MANTER A SESSÃO 
 startInLoadingState={true}
 />
 );
};

Lições aprendidas

Performance: Sincronizar o estado via API antes de abrir a WebView entrega uma experiência muito mais "nativa" do que tentar manipular o DOM da página carregada.

  • Persistência: O uso do Zustand com middleware de persistência é imbatível para lidar com carrinhos em dispositivos móveis.

  • Desenvolver soluções de e-commerce de alta performance é o que move a gente na Converte .

E você, já teve que lidar com essa ponte entre o nativo e o web no e-commerce? Vamos trocar uma ideia nos comentários!