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.