Vue Storefront is now Alokai! Learn More
State Management

State Management

We offer ready-to-use tools for handling global state management tailored for both Next.js and Nuxt3 frameworks through our dedicated packages: @vue-storefront/next and @vue-storefront/nuxt.

For Next.js, we utilize Zustand, a small, fast, and scalable state-management solution. For Nuxt3, we leverage Pinia, a state management library that is intuitive and integrates seamlessly with Vue 3. These tools are designed to simplify state management in your applications, providing robust and efficient solutions out of the box.

Our state management solutions store core data such as:

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

They also provide methods for reading and updating this data, making it easy to manage and access global state 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

To use the state management, you need to extend the alokai-context.tsx file with the state management part. All of the hooks that are returned from the createAlokaiContext function are straightforward to use. They follow the React's useState pattern, so you can read and write to the state like you would with the useState.

// sdk/alokai-context.tsx
'use client';

import { createAlokaiContext } from '@vue-storefront/next/client';
import type { SfContract } from 'storefront-middleware/types';

import type { Sdk } from './sdk.server';

export const { AlokaiProvider, useSdk } = createAlokaiContext<Sdk>(); export const {
  AlokaiProvider,
  useSdk,
  useSfCartState,
  useSfCurrenciesState,
  useSfCurrencyState,
  useSfCustomerState,
  useSfLocaleState,
  useSfLocalesState,
} = createAlokaiContext<Sdk, SfContract>();

The SfContract interface is used to define the contract between the SDK and the state management. It contains the types for:

  • cart
  • customer
  • currency
  • locale

This is needed to ensure that the state management is aware of the types that you have within the middleware, as those types can be changed within the middleware.

Initial data

There is also an option to pass initial data to the AlokaiProvider. This can be useful when you want to set the initial state of the application. You can pass the initial currencies, currency, locale, and locales to the AlokaiProvider. To do this, you need to pass the initialData prop to the AlokaiProvider component.

// components/providers.tsx

"use client";

import type { ReactNode } from "react";
import type { CreateSdkOptions } from '@vue-storefront/next';
import { SdkProvider } from "@/sdk";
import { getSdkOptions } from "@/sdk/options";
import { getSdkConfig } from "@/sdk/config";

export function Providers({ children, sdkOptions }: { children: ReactNode, sdkOptions: CreateSdkOptions }) {
  const { getSdk } = createSdk(
    sdkOptions,
    getSdkConfig()
  );
  return (
    <AlokaiProvider sdk={getSdk()}>    <AlokaiProvider
      initialData={{
        currencies: ['USD', 'EUR'],
        currency: 'USD',
        locale: 'en',
        locales: ['en', 'de'],
      }}
      sdk={getSdk()}
    >
      {children}
    </AlokaiProvider>
  )
}

Note that the Providers component is a client component. If you want to fetch some data on the server side and pass it to the client component you can fetch the data in the server component (for Alokai Storefront it will be in the app/[locale]/layout.tsx file) and pass it to the client component through props.

Usage

The state is being updated on the Storefront side. State handling is already provided with the App Router based Alokai Storefront. You can use the state management in your components or hooks and modify the state as needed. Here is an example of how you can use the state management in your components:

import { useQuery } from "@tanstack/react-query";
import {
  useSdk,
  useSfCartState,
  useSfCustomerState,
  useSfCurrencyState,
  useSfLocaleState,
} from "@/sdk/alokai-context";

function Component() {
  const sdk = useSdk();
  const [cart, setCart] = useSfCartState();
  const [customer] = useSfCustomerState();
  const [currency] = useSfCurrencyState();
  const [locale] = useSfLocaleState();

  const result = useQuery({
    queryFn: () => sdk.unified.getCart(),
    queryKey: ["cart", "main"],
  });
  // updating the cart state
  useEffect(() => {
    setCart(result.data);
  }, [result.data]);

  return (
    <div>
      <p>Cart total: {cart.total}</p>
      <p>
        Customer name: {customer.firstName} {customer.lastName}
      </p>
      <p>Currency: {currency}</p>
      <p>Locale: {locale}</p>
    </div>
  );
}

The same approach can be used in hooks or any other components.