StateKit
Overview
The State Kit pattern in the Growave SDK provides access to the underlying State Management system through a reactive interface. A State Kit combines query methods for reading data and service methods for performing mutations, all wrapped in RxJS Observables for reactive programming.
This pattern allows you to directly access and manipulate the application state that powers Growave features.
State Kit types
The Growave SDK provides two types of State Kits, depending on how their internal query and service layers are created and how they relate to the application's main state.
Shared State Kit
Shared State Kits work with the same underlying state used internally by the Growave application. Each call returns a new State Kit object, but its query and service wrap the same shared instances used by the application.
Characteristics:
- Underlying store, query, and service come from the application's shared state
- Each returned State Kit provides wrappers around these same shared instances
- State stays synchronized with Growave components
- Method names include the "Shared" suffix (e.g.,
getWishlistsSharedStateKit)
Use cases:
- When your feature must stay in sync with Growave’s UI and react to the same data changes
- When you need to read or update the shared application state instead of maintaining a separate local state
Isolated State Kit
Isolated State Kits create independent state on every call. Each State Kit constructs a fresh store, query, and service, working completely separately from Growave’s internal state and from other isolated instances.
Characteristics:
- New store, query, and service created for every call
- Each State Kit instance maintains its own isolated lifecycle
- No connection to Growave’s shared state
- Method names do not include the “Shared” suffix
Use cases:
- Custom UI features that require their own independent state lifecycle
- Local filtering, pagination, or temporary data that should remain separate from Growave’s shared application state
State Kit structure
Each State Kit consists of two main components:
Query wrapper
The query wrapper provides reactive access to read data through RxJS Observables. When you subscribe to a query, your callback will be automatically invoked whenever the underlying data changes.
Service wrapper
The service wrapper provides methods for performing data mutations, such as creating, updating, or deleting items. These methods also return Observables, allowing you to react to the completion of operations.
Available State Kits
Shared State Kits
- Wishlists Shared State Kit - Access shared wishlist state
- Products Shared State Kit - Access shared product state
Isolated State Kits
- Reviews State Kit - Independent reviews state for custom implementations
Working with State Kits
Using Shared State Kits
Shared State Kits can be retrieved once and reused throughout your application:
function onSdkReady() {
const moduleName = window.gw.sdk.common.constants.modules.WISHLISTS;
window.gw.sdk.runIfModuleReady(moduleName, () => {
window.gw.sdk.wishlists.methods
.getWishlistsSharedStateKit()
.then((response) => {
const stateKit = response.result;
// Subscribe to data changes
stateKit.query.selectAll().subscribe((data) => {
console.log("Data updated:", data);
});
})
.catch(console.error);
});
}
if (window.gw && window.gw.sdk) {
onSdkReady();
} else {
document.addEventListener("gwSdkReady", onSdkReady);
}
Using Isolated State Kits
Isolated State Kits create a new store with each call. If you want to keep state between operations, save the returned instance and reuse it instead of calling the method again.
let reviewsStateKit;
function onSdkReady() {
const moduleName = window.gw.sdk.common.constants.modules.REVIEWS;
window.gw.sdk.runIfModuleReady(moduleName, () => {
// Get the state kit once and reuse it while this feature is active
window.gw.sdk.reviews.methods
.getReviewsStateKit()
.then((response) => {
reviewsStateKit = response.result;
// Use this instance wherever you need the same isolated state
reviewsStateKit.query.selectAll().subscribe((reviews) => {
console.log("Reviews:", reviews);
});
// Fetch initial data
reviewsStateKit.service
.getReviews({ productId: 123 })
.subscribe((data) => {
console.log("Loaded:", data.items.length);
});
})
.catch(console.error);
});
}
if (window.gw && window.gw.sdk) {
onSdkReady();
} else {
document.addEventListener("gwSdkReady", onSdkReady);
}
RxJS operators
The Growave SDK provides commonly used RxJS operators through the Common module, allowing you to transform and combine Observable streams.
Accessing RxJS operators
const { map, filter, switchMap } = window.gw.sdk.common.rxjs;
Available operators
Creation operators: of
Transformation operators: map, switchMap
Filtering operators: filter, take, takeUntil, distinctUntilChanged, debounceTime, throttleTime
Combination operators: combineLatest, merge, forkJoin
Utility operators: tap
Error handling operators: catchError, retry
Best practices
Managing subscriptions
Always store your subscriptions and unsubscribe when you're done to prevent memory leaks:
let subscription;
function startListening() {
subscription = stateKit.query.selectAll().subscribe((data) => {
// Handle data
});
}
function stopListening() {
if (subscription) {
subscription.unsubscribe();
subscription = null;
}
}
Handling errors
Use error callbacks or the catchError operator to handle errors gracefully:
const { catchError, of } = window.gw.sdk.common.rxjs;
stateKit.service
.addItem(params)
.pipe(
catchError((error) => {
console.error("Error:", error);
return of(null);
}),
)
.subscribe((result) => {
if (result) {
console.log("Success");
}
});