DEV Community

Mayar Deeb
Mayar Deeb

Posted on

How to make reusable State management

Code once

If you are a programmer who likes to work with many frameworks or has to, it'll be amazing to use the same code in any framework you use, and without doing any configuration for it, just copy and paste.

- Topics we'll cover

  1. What are Services in Angular?
  2. why Rxjs ?
  3. How to Create Service that works in any farmework.
  4. How to make state Management using Rxjs.
  5. How to use Service in React component.

1. What are Services in Angular ?

Services are a great way to share information among classes that don't know each other. by using services you'll be able to:

  • fetch data form any component in your app
  • use Rxjs operators and others.....
  • use it as State management ( what we'll do now)
  • and have a clean and beautiful code

2. why Rxjs

RxJS can be used with any frameworks or Pure Javascript without doing any configuration.

RxJS is a library for composing asynchronous and event-based programs by using observable sequences.

RxJS offers a huge collection of operators in mathematical, transformation, filtering, utility, conditional, error handling, join categories that make life easy when used with reactive programming.

3. How to Create Service that work in any farmework.

  1. install the following library
$ npm install rxjs 
// or
$ yarn add rxjs
Enter fullscreen mode Exit fullscreen mode
  1. create a folder to contain all of your services, usually I name it services
    and create it in src/srvices. It doesn't matter where you create it.
    Image description

  2. create new .ts or .js file, I'll name it counter.ts (because I'm using typescript here)


class CounterService {

    private static _instance: CounterService;

    public static get Instance() {
        return this._instance || (this._instance = new this());
    }

/////...code here

}


export const _CounterService=CounterService.Instance;

Enter fullscreen mode Exit fullscreen mode

so here we create singleton class because one object should be used to coordinate actions across the system.

4. How to make state Management using Rxjs.

  1. declar your initial_state and store(BehaviorSubject)
import { BehaviorSubject } from "rxjs";

class CounterService {

    private static _instance: CounterService;

    public static get Instance() {
        return this._instance || (this._instance = new this());
    }

    private initial_state:number=5;

    private Counter = new BehaviorSubject<number>(this.initial_state);


}


export const _CounterService=CounterService.Instance;

Enter fullscreen mode Exit fullscreen mode
  1. the functions:
    1. write a function that returns your Counter as Observable so you can subscribe to it, to observe any changes.
    2. write your logic.
import { BehaviorSubject, Observable } from "rxjs";

class CounterService {

    private static _instance: CounterService;

    public static get Instance() {
        return this._instance || (this._instance = new this());
    }

    private initial_state:number=5;

    private Counter = new BehaviorSubject<number>(this.initial_state);

//step 1
  Counter():Observable<number>{
        return this.Counter.asObservable();
      }

//step 2
increment():void{
this.Counter.next(this.Counter.getValue()+1);
}

decrement():void{
this.Counter.next(this.Counter.getValue()-1);
}

incrementBy(i:number):void{
this.Counter.next(this.Counter.getValue()+i);
}


}


export const _CounterService=CounterService.Instance;

Enter fullscreen mode Exit fullscreen mode

5. How to use Service in React component.

import { useEffect, useState } from "react";
import { Subscription } from "rxjs";
import { _CounterService } from "src/services/Counter.Service";

const Index = () => {

// create Subscription array to push any Subscription we do
  let Subs:Subscription[]=[];

  const [counter, setcounter] = useState<number>();

const increment=()=>_CounterService.increment();

const decrement=()=>_CounterService.decrement();

const incrementBy=(i:number)=>_CounterService.incrementBy(i);


  useEffect(() => {

//push it to Subs to unsubscribe on component destroy 
Subs.push(
_CounterService.Counter()
.subscribe({ next: (res) => counter(res) }));

//to prevent any memory leak 
    return () =>Subs.forEach(e=>e.unsubscribe())
  }, []);

  return (
    <div>
the Counter is {{counter}}

<button onClick={()=>increment()}>increment</button>
<button onClick={()=>decrement()}>decrement</button>
<button onClick={()=>incrementBy(5)}>increment By 5</button>


    </div>
  );
};

export default Index;

Enter fullscreen mode Exit fullscreen mode

How it works

The BehaviorSubject holds one value. When it is subscribed it emits the value immediately and every time this subject gets a new value it emits it too.

note: if you unsubscribe to it you won't get any new values
the end...

you might be wondering 🤔 why Rxjs? why to use this state management and leave Redux or Context or Vuex?

the answer is if you use Rxjs as API service and State management you'll be able to copy this .ts or .js file and paste it in any project you have no matter what framework you use.
No configuration is needed. Indeed you'll have great centralized code (your API calls and your State management all in one file)

useful links 🔗

https://rxjs.dev/guide/subject#behaviorsubject

Discussion (0)