Vue Storefront is now Alokai! Learn More
State Management

State Management

The @vue-storefront/next and @vue-storefront/nuxt packages provide global state management out of the box. Under the hood, Next.js uses Zustand and Nuxt uses Pinia.

The state stores core data such as:

  • customer
  • cart
  • currently selected currency
  • available currencies
  • currently selected locale
  • available locales

Both packages expose hooks (Next.js) or composables (Nuxt) for reading and updating this data across your application.

Installation

To use the State Manager within Next.js, you need to have the @vue-storefront/next package installed. This step is already done if you have followed the Getting Started. If not, you'll find installation instructions there.

Usage

If you followed the Getting Started guide, your sdk/alokai-context.tsx already exports state hooks alongside AlokaiProvider and useSdk. These hooks are returned by createAlokaiContext and follow React's useState pattern — each returns a [value, setter] tuple.

Available hooks

HookStateType
useSfCartStateCurrent cartSfCart | null
useSfCustomerStateLogged-in customerSfCustomer | null
useSfCurrencyStateSelected currencySfCurrency
useSfCurrenciesStateAvailable currenciesSfCurrency[]
useSfLocaleStateSelected localeSfLocale
useSfLocalesStateAvailable localesSfLocale[]

The types come from the SfContract generic you pass to createAlokaiContext<Sdk, SfContract>(). This contract tells the state hooks which types your middleware uses for cart, customer, currency, and locale. Since those types can be customized in your middleware, the contract keeps everything in sync.

Initial data

The AlokaiProvider accepts an initialData prop to hydrate state on the first render. This avoids a flash of empty state during SSR. Pass currencies, currency, locale, and locales:

components/providers.tsx
<AlokaiProvider
  initialData={{
    currencies: ["USD", "EUR"],
    currency: "USD",
    locale: "en",
    locales: ["en", "de"],
  }}
  sdk={getSdk({ getLocale: () => locale })}
>
  {children}
</AlokaiProvider>

In the Alokai Storefront, this data is fetched on the server in app/[locale]/layout.tsx and passed down to the client Providers component as props. See the Getting Started guide for the full setup.

Reading state

Use the hooks in any client component to read global state. You only need the value (first element of the tuple):

"use client";

import { useSfCartState, useSfCurrencyState } from "@/sdk/alokai-context";

export function CartSummary() {
  const [cart] = useSfCartState();
  const [currency] = useSfCurrencyState();

  return (
    <div>
      <p>Items in cart: {cart?.totalItems ?? 0}</p>
      <p>Currency: {currency}</p>
    </div>
  );
}

Updating state

Use the setter (second element of the tuple) to update state. For example, changing the selected currency:

"use client";

import { useRouter } from "next/navigation";
import { useSfCurrencyState } from "@/sdk/alokai-context";

export function CurrencySelector() {
  const router = useRouter();
  const [currency, setCurrency] = useSfCurrencyState();

  return (
    <select
      onChange={(e) => {
        setCurrency(e.target.value);
        router.refresh();
      }}
      value={currency}
    >
      <option value="USD">USD</option>
      <option value="EUR">EUR</option>
    </select>
  );
}

In the Alokai Storefront, cart and customer state is synced automatically. A StateObserver component subscribes to TanStack Query observers and calls setCart / setCustomer whenever the cached data changes — so you don't need to manually sync query results into state. This component is already wired up in the storefront, so no extra setup is required on your end.