React to cart events
Run code when the cart changes by subscribing to Salla SDK events.
Use this when your UI or analytics must follow the cart: a badge count, a mini-cart, a "you added..." message.
Goal: a component that shows the live cart count.
The Salla SDK (Salla in prose, window.salla in code) emits events such as cart::updated. You subscribe in a useEffect and unsubscribe on cleanup. The SDK can finish loading after the page hydrates, so read it inside the effect, never at module scope. The full event list and the rules are in Salla SDK and events.
Write a subscription hook
It subscribes by event name, and removes the same function on cleanup. If the SDK is not ready yet, it waits for the theme::ready document event. The reference theme's mobile bottom bar uses this pattern for its cart badge.
import { useEffect } from 'react';
type CartSummary = { count?: number | string | null };
export function useCartUpdated(onUpdated: (summary?: CartSummary) => void) {
useEffect(() => {
const listener = (...args: unknown[]) => onUpdated(args[0] as CartSummary | undefined);
let bound = false;
const bind = () => {
const event = window.salla?.event;
if (bound || !event?.on) return;
event.on('cart::updated', listener);
bound = true;
};
bind();
document.addEventListener('theme::ready', bind);
return () => {
document.removeEventListener('theme::ready', bind);
if (bound) window.salla?.event?.off?.('cart::updated', listener);
};
}, [onUpdated]);
}Use it in a component
Wrap the callback in useCallback so the effect does not resubscribe on every render.
import { useCallback, useState } from 'react';
import { useCartUpdated } from '../hooks/useCartUpdated';
export function CartWatcher() {
const [count, setCount] = useState(0);
const onUpdated = useCallback((summary?: { count?: number | string | null }) => {
setCount(Number(summary?.count ?? 0));
}, []);
useCartUpdated(onUpdated);
return <span>{count}</span>;
}Check it worked
Add a product to the cart: count updates without a reload. Navigate away and back, then add again: it still updates once, not twice.
Traps
- Do not mix the two ways to subscribe. Typed helpers exist (
salla.cart.event.onUpdated,onItemAdded,onItemUpdated,onItemDeleted, each with a matchingoff...), but there is nosalla.cart.event.off(name, cb). A name-based listener is removed withsalla.event.off. - Subscribe by name in components that mount often. The reference theme avoids
onUpdatedthere because the helper wraps your callback and it leaked listeners in its case. window.sallaisundefinedduring server rendering, and a stub withouteventuntil the SDK loads. Guard the member (window.salla?.event?.on), subscribe insideuseEffect, and usetheme::readyas above.- The initial count is not an event. The reference theme also reads
salla.storage.get('cart.summary.count')once on mount. - The payload is loosely typed. Treat it as optional and fall back to a default.
Next
- Track page views: another browser-side subscription.
- Salla SDK and events: every event and the SSR rules.