How to find the right state management approach for your app

SebbySebastien Nguyen on April 1st 2022

When it comes to storing data, Vue offers us different options, but which one’s best? And why? Well, it depends on your app really. All applications have different needs and scales. There are multiple factors to consider when making that decision.

Let’s dive into the most common approaches:

  • Root Local State
  • Vuex library
  • Vue 3 composable & reactivity system

Root local state

The concept here is to use the top-level component as a Store. This requires you to pass data down to components using props. In theory, nothing’s wrong with that, this is just the normal flow of Vue. However, it is only ok for tiny applications - 1/2 level deep - after that it creates an anti-pattern known as props drilling.

Let’s say you’ve got a component tree as such:

Rows of white boxes linked by arrows to represent sate management

And you need to pass data like this:

Rows of white boxes linked by arrows to represent sate management. Three boxes are yellow, contain the word Foo and are linked with yellow arrows

By using the root component as your store, you then have to get back up to the top in order to go back down to components that need updating. 

Rows of white boxes linked by arrows to represent sate management. Three boxes are yellow, contain the word Foo and are linked with yellow arrows. Top box says Root (Foo state). Some boxes say I don't need Foo

This is not very scalable, it becomes more and more complex as your tree grows and it exposes data to components that don't need it. 

Vuex library

To solve this problem, Facebook created Redux in 2015 (based on Flux & ELM architectureVuex is the equivalent state management pattern for Vue.

The main concept of this is to aggregate all the local stores of your app into one centralised place and to make it the single source of truth.

Rows of white boxes linked by arrows to represent sate management. Separate box on right says Vuex Store (reactive)

By doing so, it allows direct communication between sibling components, in a reactive manner. That means components can now listen for store changes and get updated right away.

Rows of white boxes linked by arrows to represent sate management. Separate box on right says Vuex Store (reactive). It links via yellow arrows to three yellow boxes that say Foo updated

More descriptive details on how to use Vuex and why it needs a specific standardisation can be found here.

Well, that’s great, we now have a much better way to handle and organise all our data. But wait, when you think about it Vuex is nothing more than a reactive element that stands out of your app tree right?

Vue 3 composable & reactivity system

In September 2020, Vue released its first stable version of Vue3, which came with a lot of benefits, including the Composition API (inspired by React Hooks).

The general concept behind composition is to break down parts of our component into smaller units and to compose back up greater components with them in order to build our app. This increases code reusability and fixes inheritance issues.

More info about Composition over Inheritance can be found on Wikipedia..

This elegant new way to organise our code allows us to create our own state management system.

Let’s say we’ve got a MyCounter component that simply displays a count value and contains two buttons to increment and decrement it.

White screen with rows of code written in pink

In this example above, we are using the component local state to manage the count value and to access methods. By doing so, we are isolating the counter state within that specific component which makes it non-reusable from outside (ie MySecondCounter).

To fix this, we can outtake the logic into its own store and use the composition API to provide and inject the store wherever we need to access it (ie MyCounter & MySecondCounter).

White screen with rows of code written in pink

By doing this, we’ve made the counter store accessible from everywhere. You can now simply inject the same store into MySecondCounter component and share the same state.

Conclusion

As seen in this article, all three presented methodologies to manage states can be valid in certain circumstances. 

When it comes to choosing between Vuex and Vue 3 composable - in my opinion, there are a few things to consider. 

Vuex:

  1. It forces you to follow a certain pattern. Components trigger actions that call mutations, which then mutate the store. This could become a little verbose as your store grows. 
  2. On the other hand, this protects your store from outside mutations out of the box. This is secure and adds clarity in large scale applications.

Vue 3 composable:

  1. Not like Vuex, this gives you full power over how you would want to define your store.
  2. It allows 2-way communication between your view and state which is interesting for style binding. However, you’ll need to manually protect your store from outside mutations if needed by using the readonly methods provided by the composition API. 
  3. Not like Vuex, you will have to inject the store in every component that needs it, this could become a bit redundant.
  4. Not like Vuex, you can not use the vue-devtools to debug your store, update its state, view mutations in real-time or time travel in your application.