DEV Community

Aaron
Aaron

Posted on

The Fundamentals of State Management

Hello there! In this article, you will get to know what I have learned recently which is state management. Let's say that we have a code like this;

 let a = 0;

 function increment() {
  a +=1;
 }

 increment();
Enter fullscreen mode Exit fullscreen mode

In the code above, we declare a global variable a to be equal to 0. Then, we create a function named increment and call it. Of course, this will increment the value of the variable a. And to use this value, we can just get the value of the variable a, like:

console.log(a);

Nice! But... what if we want to do more than just console.log? Then, let's try!

function do_something() {
 console.log(a);
 // ...code logic
}
Enter fullscreen mode Exit fullscreen mode

Great! And now we can just keep calling that everytime we increment the value of the variable a. For example, in an interval, we will have a code snippet of:

 setInterval(() => {
  increment();
  do_something();
  // ...more function calls
 }, 1000);
Enter fullscreen mode Exit fullscreen mode

Awesome! Now, this is just a walkthrough of how easy it is to write a simple code that console.logs an incremented value every second, but this is not it. We need to be able to have a way to call the functions that need the variable a as a dependency without having to list them below each call of a function that changes the value of a. To do this, we can do somewhat like a subscriber pattern or, if I'm not mistaken, pub-sub.

A pub-sub means that when a client or, for example, you send me a message and I broadcast it to all the other people connected to me, then that is pub-sub.

To implement this, we can have:

 class Counter {
   constructor(initial_count) {
     this.count = initial_count;
     this.subs = new Map();
     this.subs_length = 0;
   }

   listen(listener) {
      const id = this.subs_length++;
      this.subs.set(id, listener);

      // Cleanup function
      return () => {
       this.subs.delete(id);
       this.subs_length -= 1;
     }
   }

   update() {
     for (const s of this.subs.values()) {
      s(this.count);
   }
   }

   increment() {
     this.count += 1;
     this.update();
   }
 }

 const a = new Counter;

 a.listen(console.log);

 setInterval(() => {
   a.increment();
 }, 1000);
Enter fullscreen mode Exit fullscreen mode

And there you have it! Not the most practical, but it gets the idea there in my opinion. So, let' walk through the code one last time.

A Counter interface has three properties:

  1. count (or the state)
  2. subs (a map of callback functions that get executed when state changes so they can receive the updated state. We're using a map to delete the listener easily.)
  3. subs_length (for bookkeeping and to have a unique id for each listener.).

It also has the update() method, which calls each listener in the instance of the class. It's somewhat like a chain reaction and that's all! Anyway, I was intrigued by this, so I thought about sharing it. This is one of the mechanisms as to. how reactivity works or how data changes in an environment like the frontend.

Thank you for reading and have a nice day. God bless!

Top comments (0)