Skip to Content
StoreGroups

Groups

Groups are collections of emitters, states, and other groups that are unified under a specific feature. They help organize related reactive sources into a cohesive structure, ensuring proper initialization and completion of all items as a single unit.

List of Groups

  1. Group

The group collects all subsequently created emitters, states, and groups until group.markAsReady() is called.

The group can be used as an alternative to the store when lifecycle hooks are not required, or when extending the Store class is not feasible due to other class inheritance.

import {state, emitter, group, asyncGroup} from '@bitfiber/rx'; // Defines a group that collects emitters, states, and groups const myGroup = group(); // Add group items here const someState = state<string>(''); const someEmitter = emitter<number>(); const req = asyncGroup<string, number, number>(); // Marks the group as ready, indicating that all group items have been defined myGroup.markAsReady(); // Initializes the group and all its items myGroup.initialize(); // Completes the group and all its items myGroup.complete();
  1. Named Group

The named group extracts emitters, states, and groups from the provided object and adds them to the group. Each item is accessible by the key used in the object.

import {switchMap} from 'rxjs'; import {state, emitter, namedGroup, transmit} from '@bitfiber/rx'; // Defines a named group const myGroup = namedGroup( { // Add group items here launch: emitter<void>(), data: state<number>(0), }, ({launch, data}) => { // Add interaction logic in the 'onInit' callback launch // Defines a side effect for data loading .effect(switchMap(() => getData('api/data').pipe(transmit(data)))); } ); // Initializes the group and all its items myGroup.initialize(); // Triggers the loading process myGroup.launch.emit(); // Completes the group and all its items myGroup.complete();
  1. Async Group

The async group manages the lifecycle of asynchronous actions, providing emitters for launching actions, handling success, dealing with failures, and managing the state of these actions.

import {switchMap} from 'rxjs'; import {state, asyncGroup, transmit} from '@bitfiber/rx'; interface Product { id: number; name: string; price: number; } interface ProductsState { products: Product[]; isLoading: boolean; } // Defines an async group for managing product loading const productsReq = asyncGroup<number, Product[], Error>((group, { launch, success, fail, finish, }) => { group // Keeps cached data for 120 seconds, with a maximum entry count of 10 .useCache(120, 10); launch // Defines a side effect for loading products .effect(switchMap(page => productsService.get(`api/products?page=${page}`) .pipe(transmit(group)))); success // Performs a tap callback each time the request succeeds .tap(data => console.log(data)); fail // Performs a tap callback each time the request fails .tap(error => console.log(error)); finish // Performs a tap callback each time the request either fails or succeeds .tap(() => console.log('Request has been finished')); }, []); // Provides the main state const data = state<ProductsState>({products: [], isLoading: false}, s => s // Receives request success data .receive(productsReq.success, (products, state) => ({...state, products})) // Starts the products loading process .receive(productsReq.state, ({inProgress}, state) => ({...state, isLoading: inProgress})) ); // Starts the products loading process productsReq.launch.emit(1);

Creating a Custom Group

To create a custom group, extend the AbstractGroup class:

import {AbstractGroup, emitter, state, asyncGroup} from '@bitfiber/rx'; class NotificationsGroup extends AbstractGroup { // Define your group items here }

Adding Group Items

Within the group class, define the group items you need, such as emitters, states, or groups:

class NotificationsGroup extends AbstractGroup { // Defines an async group for managing notifications loading notificationsReg = asyncGroup<void, string[], Error>(); // Defines a state to store the current notifications notifications = state<string[]>([]); }

Marking Group as Ready

To finalize the group setup and indicate that all group items have been defined,call the markAsReady method:

class NotificationsGroup extends AbstractGroup { notificationsReg = asyncGroup<void, string[], Error>(); notifications = state<string[]>([]); // Marks the group as ready #ready = this.markAsReady(); }

Adding Interaction Logic

Use the executeInnerDeferredActions method to add interaction logic:

class NotificationsGroup extends AbstractGroup { req = asyncGroup<void, string[], Error>(); data = state<string[]>([]); #ready = this.markAsReady(); // Add interaction logic here protected override executeInnerDeferredActions(): void { this.req.launch // Launches notifications request when the launch emitter emits .effect(switchMap(() => getNotifications().pipe(transmit(this.req)))); this.data // Updates data state with successful results .receive(this.req.success); } }

Adding Factory Function

To maintain a consistent style in group implementations, define a factory function for creating the group. This approach provides a standardized way to initialize groups and optionally apply additional setup logic:

export function notificationsGroup( onInit?: (group: NotificationsGroup, sameGroup: NotificationsGroup) => void, ): NotificationsGroup { const group = new NotificationsGroup(); return onInit ? group.onInit(onInit) : group; }

Usage the group

Create and initialize the group using the factory function:

// Defines a custom group const customGroup = notificationsGroup(); // Initializes the group and all its items customGroup.initialize(); // Triggers notifications loading customGroup.req.launch.emit(); // Subscribes to notifications customGroup.data.$.subscribe(notifications => { console.log('Received notifications:', notifications); }); // Retrieves notifications synchronously const notifications = customGroup.data(); console.log('Current notifications:', notifications); // Completes the group and all its items customGroup.complete();
Last updated on