Milan Saric – Technical Lead

In this article we will explore the history of state management, as well as how and when they should be used. It’s my firm belief that proper state management architecture in modern front-end projects is basically 90% of the work, afterwards it’s just simple controllers and CSS. You will find the steps and a flowchart bellow detailing when to use what type of state management, as well as various alternatives to industry standard state managers for all 3 major front-end frameworks.  

History of state management

Since we had complex JS front-end apps, we had a problem, how do we cache/reuse/store data received from the backend? Thus a need for state management was born. The first solution still used today is web storage, colloquially known as Local Storage; it’s a segmented in-browser storage solution of key-value pairs. However, it had a significant downside – a 10MB limit almost across the board.  

Thus a need for more complex storage emerged, and in the early 2010s, a new competitor emerged championed by Apple, Web SQL Database. Yet, it was quickly disposed of in favor of something that wasn’t SQL-related but rather JSON based. That standard was first released in 2015 and is now known as Indexed DB.  

With new frameworks (especially React) came the need for a new type of state management, and consequently, session storage gained traction. It was a simple in-browser storage option that lives as long as the application is alive and dies with the browser garbage collection once you close the tab. Naturally, almost simultaneously, a persistent version of this was created – with the most famous of the so-called stores being Redux. 

 Below, you’ll find various ways to store app data, as well as various ways to use said storage well.  

Web Storage

  • It’s an API supported by every browser out there.  
  • It uses built-in storage that allows you to store usually up to 10MB of key-value pairs. 
  • It’s handy when storing a language setting or other bits of data. However, if you persist a complex store, it will most likely go into local storage.  

Indexed DB

  • This API is an in-browser DB that uses JSON and is indexed by a unique key. While relatively new (since 2015), it’s considered very old and archaic, despite coming out in the same year as the famous ES6. 
  • It’s helpful if you need to store and process massive data sets on the front end. For instance, if you’re creating an Excel clone that does all the processing on the front end, you might want to use Indexed DB.   
  • While the usefulness of Indexed DB is often very niche, it can be the perfect solution

Session Storage

  • The need for this arose as single-page apps came to the fore, especially when components that needed to talk to each other were more integrated.   
  • How do you update an item in a “cart” component from a very nested component, “add to cart” that’s not a direct child of the “cart” component? Well, you update the state/context/redux/whatever your project uses.   
  • In the background, it’s just an event listener for the thing you registered in the related components.   
  • It’s used to store larger objects or when you need to manipulate data on the front end manually. Most frameworks allow built-in libraries that do this. However, those libraries can’t be persisted between sessions. 

Persistent Storage

  • Persisting session storage is possible if a state management library such as Redux is used, and in almost every case, the persisted copy is stored in Web Storage.   
  • When using a library such as Redux, it’s important to structure it well like you would a DB on the backend because having wrong “schemas”, or wrong actions/listeners will always cause unclean spaghetti code and many, many rerenders in React. (Ask me how I know).  
  • This is mainly used when there’s a need for a complex “store” that needs to persist between sessions. Think of a guest cart object in a webshop or anything else as something that can be updated between sessions before going to the backend. 

Apollo GraphQL Client

Apollo has a built-in “store” for caching GraphQL calls that functions very similarly to Redux and other alternatives. It’s a very robust solution if you’re using GraphQL, and I recommend it over any other solution if using GraphQL.  

It can also be persisted and then stored in Web Storage, however, it doesn’t need to be persisted to work.   

When you’re using GraphQL, you probably want to cache the data from the backend to allow a smoother user experience, and you probably want to use the built-in method for that through Apollo Client.  

Why Use It

Almost every front-end application needs some form of state management. If it’s a simple local storage store of a token/browser settings or a very complex Redux store, it’s essential to know when to use what, as not every tool is a hammer in state management.   

If you’re building a complete PWA-compliant application that has complex interactions between components and needs to work well in the offline mode, I recommend using a complex Redux or similar store.   

However, if you’re building a simple social network like a PWA application, you probably don’t need a complex store. Something like just Web Storage and good context design is perhaps good enough.   

However, if you’re building a very complex application with a lot of data processing in the front-end or something that will store loads of blockchain data in the browser, you probably need Indexed DB.  

And if you’re building a genuinely complex monolithic front-end application, you might need all of them in some combination. It’s very project dependent, and no single solution works for everyone. 

Redux vs. Everything Else

Redux is still the industry standard for state management in React, followed very closely by NgRx for Angular and VueX for Vue. However, all of these libraries follow the same basic principles and share the same cons. They are slow, monolithic, and are used by default even if the project doesn’t require them.  

As you’re about to see in the chart below, no state manager ticks all the boxes, and it’s critical to realize what you need for your particular application and if you want to go with the industry standard or try any of the numerous alternatives.  

React

If you need a state manager for React, try any of the alternatives mentioned – I’m sure some of them will fit your needs better than the good old Redux. I recommend Zustand since it ticks most boxes and is both tiny (~1kb) and powerful. 

Angular

Angular has lesspopular state managers, but it’s still worth it to take a look at the alternatives to see if they might fit your project better.  

Note about the charts 

The charts for React and Angular are different because the feature set depends on the frameworks and stores, and there’s a large variety of them.

Note about Vue

Vue has the de facto only state manager in the VueX, and while VueX fits the Vue paradigm quite well, nothing stops you from using MobX, for instance, especially if you have a more complex state that can accommodate two or more similar applications written in anything from Vue to Angular to React and beyond. 

Flowchart

Storage State Management Decision Flowchart 

Conclusion

When designing a new front-end application, it’s imperative that you develop the state management system properly, especially in React. In my opinion, the design of the state management system is 90% of the front-end work. The rest is simple logic and CSS.   

More often than not, you’ll be using a combination of these state management tools, and it’s vital to properly know what’s stored in Redux, what’s stored in context, and what’s stored in the in-component store. This will avoid many unnecessary rerenders, and it will reduce the complexity of the entire app significantly, thus saving countless hours.  

As we’ve seen in the flowchart, every state manager has its purpose, and we will almost always use a combination of a few managers in our app. And no matter what UI framework you use, I’d highly suggest you try one of the alternatives. Especially Zustand if you’re using React. Huge applications with millions of users require complex industry standard “stores”, but the application we write every day will benefit from something more “niche” that requires less resources but still produces the same results. 

The important thing to understand on all these is that sometimes we don’t even need a complex state manager such as Redux, and that often we can use a simpler method to speed up the development process and still arrive at the same destination. 

Author

Milan Saric – Technical Lead