Vue is already established as a major JavaScript framework. This is due to a multitude of reasons, ranging from its smooth developer experience to its extensive ecosystem. Vue’s core ecosystem and tooling is particularly admirable and is also what makes it eligible to be called a full-fledged framework.
Vue was built to be versatile, however, this versatility is very often misinterpreted by newcomers and certain seasoned developers, which tend to include a lot of tools because they think they may “need them later”. In reality, those tools are not always needed. Therefore, it is very important to understand how a tool can benefit us before adding it, or else it may turn into a disadvantage rather than something helpful.
We will now take a look at the core flux library in Vue.js: Vuex.
Vuex is the state management system in Vue.js. It is a centralized store that follows strict rules in order to help manage the state of all the components present in your Vue application.
Sounds extremely important. right? In reality, it’s a powerful tool that may or may not be helpful depending on the use case.
Vuex is a state management system. So, to understand what Vuex does, you should first have a good grasp on the concept of state in an SPA and how it interacts with the other elements.
Basically, the state is the data your components rely on. For example, the todos on your todos list, or the posts on a blog. This data is called the state, and each Vue component is allowed to have one.
As your app grows, there might be a significant increase in components. If you do not use a state management library like Vuex, each of these components will manage their own state by leveraging the Vue.js APIs designed for that purpose.
Keep in mind that Vue keeps a treelike component architecture as shown above, and also enables parent-child communication through props
and child-parent communication via events
. You can imagine how hard it may be if two distant sibling components need to react to the same data change — we will need to pass the data from child to parent til we reach the closest ancestor, then from that ancestor to the specific child (see the highlighted components on the figure above).
This is very laborious and error-prone.
That is exactly where Vuex comes in. Vuex does the job of abstracting a whole module’s state and keeping it in a centralized store, which follows Vuex’s state management pattern and communicates with your components accordingly.
That is why it is often referred to as “the single source of truth”. Though Vuex is aliased like this, that doesn’t alter the fact that components can still have their own states. You can decide to share these states with other components.
Now that you understand why we may need a state management system like Vuex, we can go ahead and make this bold assumption: there are only 2 major factors that determine whether or not you should manage state using Vue.
People often say “as your app grows, you’ll need Vuex”. Actually, it depends on the way it grows. Your app may grow but your data flow stays nuclear (i.e parent-child and close siblings).
Eventually, you can use to props and events to share this data without having to add Vuex and the boilerplate that comes wtihit.
On the other hand, as soon as you notice that your components need to have an abstract data source, it’s wise to stop using props and events and resort to Vuex. This saves you an enormous amount of time, because the later you switch to Vuex, the more you’ll need to refactor.
Sometimes we need to separate the implementation of a certain complex logic from our components, especially if this logic is related to other components in our system. A great example of this use case is authentication.
Vuex is a popular way to handle a complex app’s authentication in Vue. With Vuex, you’re able to handle the token’s availability and access controls and route blocks throughout your app. Mutations, getters, and setters assist with this task.
This pattern allows you to entirely separate the authentication logic from the app’s logic, while keeping your authentication flow traceable and your data accessible.
Vuex also eases unit testing on your whole app, which may be helpful if your app grows in complexity, making your state difficult to manage. However, you can absolutely complete testing without ever using Vuex.
Here’s a funny quote by Dan Abramov:
Flux libraries are like eyeglasses: you’ll know when you need them.
This is a very true statement. However, some say it’s possible to notice too late that you need a flux library. Unfortunately, this will force you to introduce a complex flow to an already complex application.
Based on the two major factors I cited above (app size and data complexity), I created this little flow chart to help developers decide right from the project planning step if they will need Vuex to supercharge their app:
There’s also a section in the Vuex docs that briefly explains when you should probably use Vuex.
When you create a new Vue.js app using the Vue-CLI, it doesn’t bug you by asking if you need a state management system. It just doesn’t include it. Though it’s extremely versatile, Vue.js aims to be very approachable and tries to make your new project as simple as possible.
A major reason people avoid Vuex is that Vuex is verbose. It needs to be — it has to follow a pattern in order to ensure that changes to your state happen on purpose. Below is a basic todo component that uses Vuex, compared to another that doesn’t:
The code above shows how cumbersome your code will become when using Vuex to manage your state in a very simple app. In cases like this one, it’s best to skip out on Vuex and resort to props and events or another simple state management pattern.
While working on a medium to small app, you have a handful of options you can explore if you don’t want to get entangled into Vuex’s verbosity. Some of these methods require you to write simple state management from scratch, and others require using 3rd party libraries. You get to use what works best for you depending on the way you want to structure your code.
It’s not a bad idea to use another flux library besides Vuex. Though they may serve the same purpose, they often differ in usage. Some may provide less boilerplate compared to Vuex, which may fit your use case.
GitHub – vuejs/pinia: 🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support
🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support – vuejs/pinia
GitHub – Andy-set-studio/beedle: A tiny library inspired by Redux & Vuex to help you manage state in your JavaScript apps
A tiny library inspired by Redux & Vuex to help you manage state in your JavaScript apps – Andy-set-studio/beedle
GitHub – alexander-heimbuch/redux-vuex: Redux bindings for VueJS inspired by Vuex.
Redux bindings for VueJS inspired by Vuex. Contribute to alexander-heimbuch/redux-vuex development by creating an account on GitHub.
GitHub – andrewcourtice/harlem: Powerfully simple global state management for Vue 3
Powerfully simple global state management for Vue 3 – andrewcourtice/harlem
GitHub – mediv0/v-bucket: 📦 Fast, Simple, and Lightweight State Manager for Vue 3.0 built with composition API, inspired by Vuex.
📦 Fast, Simple, and Lightweight State Manager for Vue 3.0 built with composition API, inspired by Vuex. – mediv0/v-bucket
I’d recommend that anyone pick Vuex rather than following this method, because realistically you’ll just end up recreating Vuex. However, If you ever need a “custom” source of truth, you can also implement one yourself using the Vue.reactive
method.
Keep in mind that for it to be a reliable source of truth, changes should occur only on the basis of a mutation, or else you’ll find yourself with untraceable bugs.
In its docs, Vue provides a little guide to help developers create their own centralized state management system.
Vue also enables you to pass data throughout your app via a global event bus. You can read this article for a detailed tutorial on how to do this: https://blog.logrocket.com/using-event-bus-in-vue-js-to-pass-data-between-components/.
If you are using Vue 3, it’s a good idea to use a third party library like tiny-emitter or mitt to act as your event hub as suggested in the docs.
Vue’s composition API’s motivation is to enable a better logic reuse and code organization in Vue apps. The composition API brings a modular pattern in Vue that enables you to flexibly compose your component’s logic.
With this elegant pattern, as explained by Andrej Galuf, it is possible to use the composition API as a store. You can compose a function that will later serve as your shared store. This will significantly reduce the boilerplate on a smaller app as compared to what Vuex may bring.
// @/services/counter.js import { ref, computed } from '@vue/composition-api' const count = ref(0) export const getCount = computed(() => count.value) export const increment = () => count.value += 1
// @/components/ComponentA.vue <template> <div id="component-a"> <button @click="increment()">Increment Counter</button> </div> </template> <script> import { createComponent } from '@vue/composition-api' import { increment } from '@/services/click-counter' export default createComponent({ setup() { return { increment } } }) </script>
// @/components/ComponentB.vue <template> <div id="component-b"> Clicks: {{ getCount }} </div> </template> <script lang="ts"> import { createComponent } from '@vue/composition-api' import { getCount } from '@/services/click-counter' export default createComponent({ setup() { return { getCount } } }) </script>
Vuex also has plugins that may help simplify the boilerplate. For example, we have the Vuex-pathify plugin, which helps you access deep properties in the state without using the getters property — you can do so with a path. For example, you can use [email protected]
. Vuex pathify also enables you to set up mutations with a single path.
GitHub – davestewart/vuex-pathify: Vue / Vuex plugin providing a unified path syntax to Vuex stores
Vue / Vuex plugin providing a unified path syntax to Vuex stores – davestewart/vuex-pathify
There’s no doubt that Vuex is a great tool. However, with great power comes great responsibility. One of these responsibilities is understanding its power and deciding to leverage it or not at the cost of having a more complex codebase.
Most of the simple applications out there are fine with Vue’s event and props data communication pattern. These apps will tend to become much more complex if we add Vuex. Besides, Vue.js offers great tools like the composition API and top tier reactivity, which could do the job in a much better and simpler way than Vuex.
Next time you are working on your awesome Vue project, be sure you actually need Vuex before adding it.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSOLID principles help us keep code flexible. In this article, we’ll examine all of those principles and their implementation using JavaScript.
JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.
3 Replies to "Do you really need Vuex?"
Great article,I learned a lot. Thanks!
Excellent article. However I’m wondering if what I’m doing now is good enough for certain basic purposes at least. I’m using a config.js file that I import in my main.js and enter into the global “domain” via Vue.prototype (ie Vue.prototype.settings). Then I’ve been able use the data as ie. `{{ settings.companyName }}` in some of my templates. This is only meant for config constant data, and it seems to work fine but wondering if I should use Vuex anyhow.
Thanks for taking the time to write this article.
I think the screen shot comparing with and without vuex in the `Why would you skip out on Vuex` section doesn’t really provide an accurate depiction of what the todo list app would look like without vuex. First it is missing all of the code to persist the data into the array. This code is essentially all the code within the mutators of the vuex store, with some minor modifications. In addition the vuex example has a changed method that isn’t used as far as I can tell.