Reactivity in Vue.js apps using Vuex
What is Vuex?
If you are a web developer using Vue.js, you probably know what Vuex is, but as its landing describes: “Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion”.
Using a centralized state is great for medium-large SPA (single page applications) but, if we are not very used to taking advantage of Vue’s reactivity we can face some problems here.
In this article, we will cover some reactivity problems we can face and how to face them, especially using Vuex states.
Creating a store to manage the state of a SPA
As an example, we are going to create a Vuex store to manage the state of a small SPA for taking notes, in which we will support creating and editing notes.
To start, let’s create the Vuex store file (store.js) which will contain the state, the mutations and the actions. If you need some guidance about Vuex (state, mutations and actions), you can go to the docs here: https://vuex.vuejs.org/guide/state.html
Each note will be a simple object containing its title and content (to simplify we’ll use title as identifier). To store them, we will create an array called “notes” inside the state.
Now let’s program adding notes functionality. For this, we will start creating a mutation and an action store which will add the note to the “notes” array. Don’t forget whenever we want to modify the state we always have to do it using mutations.
After this, if we commit the addNote mutation everything works as intended, nice!
But let’s go deeper, now it’s time to implement the edit functionality, creating an action which will have to find the note to edit and modify it. The action will look for the note to edit (by its name) and if the note exists, will commit the mutation in order to replace the old note with the edited one.
If we call editNote action, the state has been modified but… we are not aware of it! That’s because this mutation did not trigger any update. But… if adding an element to the array triggered the update, why modifying an element didn’t? For performance reasons, not every object/array modifications trigger updates, so what happens if I need those updates? This is where the magic begins.
Vue.js provide us a way to do the modifications triggering updates, using Vue.set function https://vuejs.org/v2/api/#Vue-set
So, in order to make this commit work as we want it to, we have to use Vue.set instead of directly accessing the element inside the array.
Now this works as expected, but let’s suppose we are now required to be able to add an author to notes. As we did with editNote, we are going to create an action and a commit to implement this functionality.
But… this is not working, what’s happening? We are having the same problem we faced earlier, we are not triggering reactivity updates so even after modifying state we don’t see it in the app. The way to solve it is the same one as earlier, use Vue.set to modify the object in order to trigger the updates.
Voilà, problem solved… this is working fine! So, the goal of the post is to explain that:
- Not every change in objects and arrays trigger reactivity updates.
- If we need it to trigger the update (we don’t always need it), we can use Vue.set (even inside Vuex stores!) to trigger the updates in the modifications.
Having this clear, you can go to the docs to see more examples of triggering and not triggering modifications inside arrays and objects: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
Frontend Developer at Geoblink