Vue Store Actions

Posted on  by admin

In Vuex, actions are functions that call mutations. Actions exist because mutations must be synchronous, whereas actions can be asynchronous. You can define actions by passing a POJO as the actions property to theVuex store constructor as shown below.

To "call" an action, youshould use the Store#dispatch() function. The obvious question to ask about actions is "why actions?" Vuex stores have a commit() function that lets any function commit mutations, so you could just as easily do this:.

Dispatching Actions #

In isolation, the async function approach above is better because it doesn't depend on any particular framework.You can just call a function and that's it. Plus you can just use incrementDelay() as a method on your Vue instanceand get error handling for free.

A note from JavaScript In Plain English

But there's one very cool benefit of using actions: the subscribeAction API. Vue lets you register a callback that Vue will callevery time an action is dispatched. The subscribeAction() API is the basis for many Vuex plugins, sousing actions can let you better leverage the Vue community's plugins. Actions are great, but how do you use them with Vue components? Vuex has a neat mapActions() function that converts actions to Vue instance methodsas shown below.

Vue School has some of our favorite Vue video courses. Their Vue.js Master Class walks you through building a real world application, and does a great job of teaching you how to integrate Vue with Firebase. Actions are similar to mutations, the differences being that:. Instead of mutating the state, actions commit mutations. Actions can contain arbitrary asynchronous operations. Let's register a simple action:. Action handlers receive a context object which exposes the same set of methods/properties on the store instance, so you can call context.commit to commit a mutation, or access the state and getters via context.state and context.getters.

We can even call other actions with context.dispatch. We will see why this context object is not the store instance itself when we introduce Modules later.

In practice, we often use ES2015 argument destructuring to simplify the code a bit (especially when we need to call commit multiple times):.

Vuex Store Tutorial

Actions are triggered with the store.dispatch method:. This may look silly at first sight: if we want to increment the count, why don't we just call store.commit('increment') directly? Remember that mutations have to be synchronous.

We can perform asynchronous operations inside an action:. Actions support the same payload format and object-style dispatch:. A more practical example of real-world actions would be an action to checkout a shopping cart, which involves calling an async API and committing multiple mutations:.

Note we are performing a flow of asynchronous operations, and recording the side effects (state mutations) of the action by committing them.

  1. You can dispatch actions in components with this.$store.dispatch('xxx'), or use the mapActions helper which maps component methods to store.dispatch calls (requires root store injection):.
  2. Actions are often asynchronous, so how do we know when an action is done?

And more importantly, how can we compose multiple actions together to handle more complex async flows?

The first thing to know is that store.dispatch can handle Promise returned by the triggered action handler and it also returns Promise:.

  1. Now you can do:. And also in another action:. Finally, if we make use of async / await, we can compose our actions like this:.
  2. It's possible for a store.dispatch to trigger multiple action handlers in different modules.
  3. In such a case the returned value will be a Promise that resolves when all triggered handlers have been resolved.

Modified1 year, 11 months ago. Im using VueJS and Vuex. I have the userid into the store, this way:vuex screenshot. And i try pass the userid to a fetch, but vuejs return error .

([Vue warn]: Error in created hook: "TypeError: this.$store is undefined"). First, when referencing the store within vuex files:.

context.state instead of this.$store.state. context for all of the this.$store. So, context.commit and context.dispatch. Second, the loadProducts needs to be rewritten as an actionper docs. Third, loadProducts needs to incorporate the context as a parameter:. As @phil has mentioned in this thread, it is important to view the documentation entirely, as this single answer will get you on the way to debugging the problem, but there might be multiple more problems showing up (e.g.

What's the Point of Actions?

fetch errors, file structure errors, component/App level errors). 22 gold badges1111 silver badges2424 bronze badges. 2424 bronze badges. In the previous article in this series we discussed what a store is, why it's useful, and when it's a good time to implement one.

With those principles in mind, we can now look into how to implement a store with Vuex.

Vuex is the official store library and state management pattern for Vue.js. It has the advantage of being the first store for Vue and thus has been used in thousands of projects by thousands of developers all over the world and is time tested to be effective.

The problem

Let's take a look at how it works. To note, if you are using Vue 2 you'll want to use Vuex 3. I'm going to be showing examples in Vuex 4 which is compatible with Vue 3 but there are only a few differences so most everything described here will be applicable.

Vue School also offers a free Vuex course if you'd like to dive deeper into Vuex. In order to get started with Vuex, you can install it with npm or yarn. Then instantiate it via a createStore() function much like Vue 3's createApp() function. Lastly, you register it with Vue like any other Vue plugin with the use() method.

Stores in Vuex are defined via an object passed to the createStore function.

The object can have any of the following properties: state, getters, mutations, and actions. The store's state is defined in the state property. State is just a fancy word meaning the data you want keep in your store.

You can think of it as the data property on a component but available to any of your components. You can put any kind of data you want in here like the logged in user we mentioned in the previous article.

Dispatching Actions in Components #

Also different properties defined in the state can be any data type you'd like, such as objects, arrays, string, numbers, etc. In order to access the store's state in any component template you can use$store.state[propertyNameHere]. For example, in order to access the user's name in a profile component we do the following:. Or we can clean up the template a bit by using a computed property.

Wrapping it up

Making the computed properties in this way can get more and more verbose as you continue to access the store's state from your components. In order to lighten things up, you can use one of the Vuex helper functions mapState, passing it an array of the top level properties from the state we want access to in the component. mapState is even a little more flexible than this but this is usually enough for 90% of my use cases.

If you feel like sharing your knowledge, we are open to guest posting - and it's free. Find out more now.

Besides the data itself stored in the state, the Vuex store can also have what's known as "getters". You can think of getters as the store version of computed properties and just like computed properties they are cached based on dependencies.

  • All getters in Vuex are functions defined under the "getters" property and receive the state as well as all the other getters as arguments.
  • Then whatever is returned from the function is the value of that getter.
  • Accessing the store's getters is much the same as accessing the state except you look under the getters property instead of the state property.
  • You could also use a computed property in your component or a helper function (this time mapGetters) like with the state.
  • If you remember from the previous article in the series, a defining principle of a store is having rules on how the store's data can be changed.
  • The Vuex state management pattern assigns this responsibility to actions and mutations.

Vuex is the only one of the solutions discussed in this series that make a distinction between these 2 concepts. This is the short and sweet of it:. Mutations are always synchronous and are the only thing that are allowed to change the state directly. A mutation is responsible for changing only a single piece of data. Actions can be synchronous or asynchronous and shouldn't change the state directly but call the mutations.

More Vue Tutorials

Actions can invoke multiple mutations. Also here's some more info and best practices for each. MutationsIt's convention to uppercase mutation namescalled via commit('MUTATION_NAME', payload)payload is optionalShould not contain any logic of whether to mutate the data or notIt's best practice to only call them from your actions (even though you do have access to calling them in components).

It's convention to uppercase mutation names. called via commit('MUTATION_NAME', payload). payload is optional.