Write your own javascript state management library

Rogerio Amorim
The Startup
Published in
5 min readJul 6, 2019

If there’s one thing that’s omnipresent when we talk about javascript application development is state management. If you don’t know what is state or state management and why it’s so important nowadays, you may want to read this article from David Meister or some of the others available in Medium about this subject.

There are a lot of ready popular solutions out there, like Redux, Mobx and Vuex, and there’s a lot of documentation about how to use these solutions, making it easy to adopt one of them in your projects.

That’s more than enough for almost everybody, but some (like myself) may wonder how these magical libraries work under the hood. To help with this, I tried to build my own simple state management library to use in smaller projects, and this article is about what I could achieve.

State management is basically a two-way path management: you should let your application update the state and you should notify other parts of your application that the state has been changed, so they could react to this and do whatever they need to.

The first part is the easy one. All we have to do is write a class that has an internal state (an object) and a method that when called change this state accordingly to the new state received by the method.

For this we’ll use getter and setter pattern to retrieve the state and to deny directly state changing (return false).

To change the state in an immutable way, we’ll provide the setState method. and we’ll make it possible to set the initial state by using the constructor method.

In the state get method we return a new object that’s a clone of the internal state, so the consumer won’t keep a reference to the internal state.

Another important feature we’ll be using is the classes private properties that’s being implemented in the ECMA Standard. If you don’t know what I’m talking about, maybe you should read this documentation and then proceed with the reading.

This feature is not available in current browsers, so in order to use it you have to install (npm install — save) and specify in you .babelrc file the @babel/plugin-proposal-class-properties plugin, like below, and then use babel to compile the library.

We’ll be adding two simple helper functions as well: one to clone an object and another to check if the value passed is an object.

After all this explanation, the starting code looks like this:

With this part done, now let’s head to the second part. To accomplish this we must think about a way to let other parts of the application know the state have changed. For this we’ll be using one very know pattern in the development world: pubsub, or publisher-subscriber.

According to wikipedia, publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead categorize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are”. If you haven’t understood what it is or want to know more about it, you can read this article of hackernoon that explain pubsub and observer pattern.

So we’ll change our state management and add a Pubsub class with the publish and subscribe methods. This class will be used by the setState method of the Store class to manage the subscribers notifications. Another change is the addition of the subscribe method to the Store class that simply calls the subscribe method from the Pubsub class. This way, when we want to execute some code on the state change, we call the subscribe method passing the function that should be called. This callback function will receive the next state, so it can react to it. The code now looks like this:

Now we can test our state management solution with the code bellow:

By executing this code, you’ll see that everything works and whenever the state is modified, both callback functions are called and the state is logged in the console.

This seems good for small applications, but in most cases we only want to execute the callback function when certain parts of the state are modified, otherwise we can have unnecessary code execution, leading to performance issues. The pubsub pattern implements this using named channels. So whenever you want to subscribe, you need to inform the channel you’re interested. The same happens to the publish method, you must inform in wnich channel the information must be published, so the correspondent subscribers are notified.

This kind of solution doesn’t seem optimal, at least to me. So we’ll try to make another type of implementation. where subscribers have to inform in which part of the state they’re interested in.

In the available solutions in the market, there’s one that implements this kind of solution the most easy way (IMHO): React-redux connect method. As you can verify in their documentation, the connect method first parameter, mapStateToProps, is a function that receives the updated state and returns an object that is part of this state. This way the connect method knows if it must update the component’s props or not.

We can do the same in our little state management library. Whenever someone wants to subscribe to the state changes, it will pass the callback function and other function similar to the mapStateToProps. We’ll call this second function the config function from now on.

With this assumption, well change our subscribe method to receive these two functions and store them in an object ({ callback, config}) in the callbackList array. In our publish method, we’ll receive the current and next state that is stored in the Store class. Then inside the loop that’s responsible to call the callback functions, we’ll apply both states to the config function of each subscriber and check if they’re not equal. When this is true, we’ll then call the callback function passing the result of the next state applied to the config function. It all seems too difficult when reading like this, but as soon as we make the code you’ll see it’s very simple.

We’ll implement also another helper method, isEqual, responsible for the object comparisons. It’s very simple and just uses the JSON.stringify method to determine if two given objects are equal or not.

So the final code looks like this:

We’ll modify the test code we’ve already written so the first callback is only called when a is changed in the state and the second callback is called only when b value is changed.

When you execute the code above, the first callback will be called two times, and the correspondent a value will be logged. Then the second callback is called twice, logging only b value, first 1 then 2. The a value is not logged because it’s not defined in the second config function.

So I think we’re don here and have accomplished what this article was supposed to achieve.

Hope you all enjoy.

Any suggestions or observations are welcome as always.

P.S.: If you don’t want to use babel to build the code, I’ve left the final code without the private class parameters and the test part in jsbin so you can play with it.

--

--