Easily create your own NGRX | Redux store
Tags: angular, rxjs, reactivex, typescript
Published: 2022-01-14 09:51:07


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)

---

![You will see it's easy !](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5351357hfwnkcv8sc2mb.jpg)
You will see it's easy !

To do that we will use **RxJS** (and optionally but i definitely recommend it, [ts-deepmerge](https://www.npmjs.com/package/ts-deepmerge))

We will also create a provider and annotate it with :

- ![Singleton Provider](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95tckdeh3j5ygh8rvery.png)

 
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' }.

![Store default](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/831j2ki7frwhckfcgclh.png)
 

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 :

![Emit and Listen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s7eaedk3hcx6wbolsd4y.png)
 

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.

![Filter store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t41l8ssyllywtdcpkihk.png)
 
This is an example of store you can use.

And if you wanna listen only one property you can use listen like this :

![By Property](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ypxobhpvobcw9vs34zy.png)
 

 
Or like this if you wanna the global store :

![Use global store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7cjemsfhwefyaq169njf.png)

For the use of emit, is simple, update what you need to update and that it 

![Update store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2uon4fr8of060rjkgy1o.png)
 

So now you can use your own store, not bad no ?

![Not Bad](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d0i9ciozvf4msb8qvyp4.png)
 

You can also go futher and customize it with your needs, etc...

See you soon !

Full code :
```typescript
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 🚀] (https://dev.to/thekiba), 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](https://dev.to/thekiba/rxjs-in-practice-writing-our-own-ngrx-290i)


(Also posted this article at Angular Nation, Join us ! https://www.angularnation.net/posts/easily-create-your-own-ngrx-redux-store)