Easily create your own NGRX | Redux store
NOPR9D ☄️
Posted on January 14, 2022
Easily create your own NGRX | Redux store
So you wanna use a store but you also wanna make it yourself, with a few lines of codes. (code at the end into a gist, we are with angular here, but you can do it anywhere)
To do that we will use RxJS (and optionally but i definitely recommend it, ts-deepmerge)
We will also create a provider and annotate it with :
Cause we wanna only one instance of our StoreProvider on all our app.
We also need two property (from RxJS) into our StoreProvider, a BehaviorSubject and an Observable.
In case of you never use RxJS i give you a quick description of this two weird object :
Observable:
It's an entity who provide async events.
You can Subscribe to it (listen for new events/value, or call a callback at each update, etc ...)
Be careful, cause if you Subscribe after the observable's update, you will miss it, and on the first subscription, he hasn't got an initial value.
It's also called a hot observable (short explain : cause you can miss the update).
BehaviorSubject:
It's an entity who provide also async events, but he got an initial value.
Same recommendation as for the observable but with a variant, if you listen after the update, you will not had the initial value, but the last updated value.
It's also called a cold observable (short explain : cause the last update is stored).
Now let's code !
So we get our class StoreProvider with our two property store and store$, the default value four our store if the object : { value : 'I am a default value' }.
You remember when i said we will do it easily ? Now you just need two functions, Emit and Listen.
Emit : used to update our store
Listen : used to listen when our store is updated
To do it we need two RxJS operators, Filter and Map.
Filter : Useful if we want listen emition by condition (you don't be notified if the filter return false)
Map : Useful if we want map the updated value, in case of store with deep object.
Now the two function :
The function merge is from import merge from 'ts-deepmerge';
The Native equivalent is : const combined = {...this.store.value, ...store}
But is can be weird on realy deep object.
Like you see you can use a large store and filter it by property.
This is an example of store you can use.
And if you wanna listen only one property you can use listen like this :
Or like this if you wanna the global store :
For the use of emit, is simple, update what you need to update and that it
So now you can use your own store, not bad no ?
You can also go futher and customize it with your needs, etc...
See you soon !
Full code :
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import merge from 'ts-deepmerge';
@Injectable({ providedIn: 'root' })
export class StoreProvider {
private store: BehaviorSubject<any> = new BehaviorSubject<any>({value:'I am a default value'});
private store$: Observable<any> =this.store.asObservable();
public emit(store: any): void {
const combined = merge(this.store.value, store);
this.store.next(combined as never);
}
public listen(
property?: string
): Observable<any> {
return property
? this.store$.pipe(
filter((value) => value && value[property]),
map((value) => value[property])
)
: this.store$.pipe(filter((value) => value));
}
}
You also had the article from 🦊 Reactive Fox 🚀, which provides more explanation and another way to do the same. (I used his articles a lot when I learned RxJs ^^)
cf : RxJS in Practice
(Also posted this article at Angular Nation, Join us ! https://www.angularnation.net/posts/easily-create-your-own-ngrx-redux-store)
Posted on January 14, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.