Component Store Made Smarter
Inheritance for Hassle-Free CRUD. Reuse, Don’t Redo.
TECHNICAL


Inheritance in programming is like a tree — branches (child classes) grow from a strong trunk (parent class), sharing its core strength while spreading in unique directions.
Photo by mohammed hassan on Pexels
We often perform repeated operations while working on any feature. Few of such operations are Create, Read, Update and Delete (CRUD).
Any feature involves creating data by fetching details from the user and saving it to the database. Reading that data from the database to display to the user. Allowing the user to update the data and also to delete the data.
Any component store constitutes of the following:
Interface
Every component store has a structure that is determined by an interface that will be provided to the ComponentStore class.
Effects
Effects carry out the side-effect operation such as API calls and error handling for such calls. In Effects, we perform the following common operations:
Check the pagination parameters if it is a paginated API before making the call
Make an HTTP call, and perform response handling (both success and error)
Storing the response to state
Updater
Updaters allow us to update the value of the store. It can be carried out in following ways:
Make call to patchState (partial update) or setState (complete reset) to update the stored value
Make call to updater function to update store by extracting business logic out of components
Selectors
Each time the store is updated, the Selectors provide that updated value to the component. Selectors are subscribed in the component to display the stored value.
Carrying out above operations are often repetitive and almost required in every feature utilizing a component store making it a tedious job.
What if I give you a way to make them less repetitive and more fun?
Based on above discussion, consider the following component store with basic CRUD handling for an e-commerce website:
Normal Component Store for handling CRUD operations
Breakdown
In the above component store file, we have:
Selectors for reading the different values such as API response data, loading progress and pagination details
Effects for making the API call with logic to handle the pagination. It also displays a toast message on API failure
Updater to update store values
Respective data interfaces
Notice the Lines of Code (LOC) that you need to write to perform a single operation — let alone handle the entire CRUD process. For each feature you need to write similar LOC.
It’s now time to introduce the parent component store…
Parent Component Store


Photo by Tom Fisk on Pexels
We will first work on the component store initialization. Our parent component store will have to perform two operations:
Take the store data from the child class (common + specific data) and provide to ComponentStore class
Carry out the common CRUD operations on the data
The operation looks like:


Flow between the Component Stores
The global data will be shared with the concept of Injection Token.
Let’s call the token COMPONENT_STORE_COMMON_DATA. We want this token to be global so that any component store can use it to access the common data. It should have its default value that will be used for the common CRUD operations.
The definition will look like:
Injection Token for the global component store data
Breakdown
providedIn: ‘root’:
This means the token and its provided value (resolved via the factory) are registered globally in the root injector.
The token will be available throughout the application without explicitly adding it to a providers array in a module or component
factory: () => STORE_INITIAL_STATE:
The factory property is a function that returns the value to be associated with this token. Here, it will return the value of STORE_INITIAL_STATE.
This factory is executed once when the DI system resolves the token for the first time.
Whenever this token is injected, it will have this default value of STORE_INITIAL_STATE.
Now let’s create parent component store:
Parent Component Store
We are using generics to make the parent store reusable. Any child store to this parent store will look like:
Child Component Store
Breakdown
Creation of child component store’s interface IChildComponentSpecificStore. This interface extends IDataAccess and forms the structure of common data. I took ICommonData as reference to represent the data type for the common CRUD data
additionalData represents the additional child store specific data. For the sake of simplicity, I have used just one additional key, but it can be extended to represent large data sets
INITIAL_STATE represents the default value of child store specific data
The child component store injects the global store token which has value of STORE_INITIAL_STATE, combines it with INITIAL_STATE value and passes to the parent for the ComponentStore initialization
Since the parent is initialized by the child’s constructor super call, its value of token gets overridden by the provided value forming a combined value of global and local state in the parent store. The same is used to initialize the ComponentStore.
In a similar fashion, you can move the common operations in the form of utility functions. One such example is updating data after the API call, common data selectors, injecting common services, etc.
An example will look like:
Final Parent Component Store
Now if you observe, we haven’t made any changes to the ChildComponentStore yet, still the child store has all of it!
Let’s take another look at the updated CrudStore, we discussed earlier:
Final Crud Store with Inheritance
See, all the redundant code got vanished away… 🌟
The sky is the limit — there are no boundaries to how high you can go.
You can add any and every common functionality in the parent store and utilize it in the child store.
You can even reuse effects! 😉