Skip to content

Store & Provider Boundary

Use a scope for local state. Use a store when state should be shared through a React subtree or owned by a domain.

createStore(name, setup) returns a tuple:

Tuple itemUse
useStoreRead the store inside React components
getStoreAccess the store inside another store setup or a scope factory
import { createStore, observable, StoreProvider } from "@usels/core";
const [useCartStore, getCartStore] = createStore("cart", () => {
const items$ = observable<Record<string, number>>({});
const count$ = observable(() =>
Object.values(items$.get()).reduce((total, quantity) => total + quantity, 0)
);
const addItem = (id: string) => {
items$.set((items) => ({ ...items, [id]: (items[id] ?? 0) + 1 }));
};
return { items$, count$, addItem };
});
function App() {
return (
<StoreProvider>
<CartButton />
</StoreProvider>
);
}
function CartButton() {
const { count$, addItem } = useCartStore();
return <button onClick={() => addItem("keyboard")}>Cart {count$.get()}</button>;
}

StoreProvider owns the store registry for its subtree. That boundary matters for SSR requests, tests, embedded roots, and app shells because every provider gets isolated store instances.

Use getStore() inside another store setup function or inside a "use scope" factory rendered under a provider:

function StoreBackedSearch() {
"use scope";
const { setQuery } = getSearchStore();
const draft$ = observable("");
observe(() => {
setQuery(draft$.get());
});
return <input value={draft$.get()} onChange={(event) => draft$.set(event.currentTarget.value)} />;
}