Is it possible to dispatch actions from getters in Vuex?

Fiddle : here

Currently, I am in the process of developing a web application using Vue 2 with Vuex. Within my store, I aim to retrieve state data from a getter. My intention is for the getter to trigger a dispatch and fetch the data if it discovers that the data has not yet been populated.

This is how my Vuex store looks like:

const state = {
  pets: []
};

const mutations = {
  SET_PETS (state, response) {
    state.pets = response;
  }
};

const actions = {
 FETCH_PETS: (state) => {
      setTimeout(function() { 
            state.commit('SET_PETS', ['t7m12qbvb/apple_9', '6pat9znxz/1448127928_kiwi'])
    }, 1000)
 }
}

const getters = {
    pets(state){
    if(!state.pets.length){
        state.dispatch("FETCH_PETS")
    }
    return state.pets
  }
}

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters
});

However, an error message keeps popping up:

Uncaught TypeError: state.dispatch is not a function(…)

I am aware that this can be resolved by implementing it within the beforeMount hook of a Vue component. But considering that I have multiple components utilizing the same Vuex store, I need to decide on a single component for this implementation and understand its implications on the other components.

Answer №1

It is important to note that getters are unable to call dispatch since they receive the state rather than the context of the store.

On the other hand, actions have the ability to call state, dispatch, and commit because they are provided with the context.

The primary purpose of getters is to manage a 'derived state'.

If you opt to set up the pets state on the components that need it instead, you can simply execute FETCH_PETS from the root of your application, eliminating the necessity for the getter.

Answer №2

While browsing through some older discussions, I came across a method that caught my attention for dispatching from a getter in my store module:

import store from "../index"

I incorporated the store within my getter by using this approach:

store.dispatch("moduleName/actionName")

This tactic was employed to ensure that data was accessible even if it had not yet been retrieved.

*revision: I feel it is important to draw your attention to the following resource: Vue form - getters and side effects

This subject ties back to @storsoc's observation.

If you find yourself needing to dispatch actions from your getter, it may indicate a flaw in how your state is structured. Perhaps an ancestor component should have fetched the necessary data beforehand (state lifting). Additionally, bear in mind that getters ought to be utilized when deriving new data from the existing state before presenting it in your template; otherwise, you can refer directly to the state like so: this.$store.state.variable for use in methods/computed properties.

Consider incorporating these considerations into your lifecycle methods. For instance, in your mounted or created methods, you could verify if the state has been initialized and dispatch if necessary. If your getter / "direct state" resides within a computed property, it should automatically register any changes.

Answer №3

Encountered a similar issue.. was looking to have all Vue instances automatically load certain content, so I created a mixin:

store.registerModule('session', {
    namespaced: true,
    state: {
        session: {hasPermission:{}},
        sessionLoaded:false
    },
    mutations: {
        changeSession: function (state, value)
        {
            state.session = value;
        },
        changeSessionLoaded: function (state)
        {
            state.sessionLoaded = true;
        }

    },
    actions: {
        loadSession(context)
        {
            // Ajax request that sets context.state.session=something
        }
    }
}); 

Vue.mixin({
    computed: {
        $session: function () { return this.$store.state.session.session; },
    },
    mounted:function()
    {
        if(this.$parent==undefined && !this.$store.state.session.sessionLoaded)
        {
            this.$store.dispatch("session/loadSession");
            this.$store.commit("changeSessionLoaded");
        }
    },
});

By implementing it to load only once per vue instance and store, and automatically including it in every Vue instance, there is no need to define it in every main app.

Answer №4

To dynamically configure a page, I implement a getter that looks something like this:

getter: {
  configuration: function () {
    return {
      fields: [
        {
          component: 'PlainText',
          props: {},
          setPropsFromPageState: function (props, pageState, store) {
            // custom logic
          }
        }
      ]
    };
  }
}

When setting props on a dynamic component within the page component, I utilize the

setPropsFromPageState(field.props, this.details, this.$store)
method. This allows for config-level logic to modify the props values or trigger actions if necessary.

This callback function, stored in the getter, is executed in the component's context and has access to $store through it.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Deliver feedback from NodeJS Server to JavaScript on the client side

I have set up an HTTP server in NodeJS by utilizing the http.createServer(...) method. In my client-side JavaScript file, I sent a query using the POST method to the localhost URL. The server effectively received the data from the client, but now I am enco ...

Countdown Clock in JavaScript for Automatic Logout

I am currently working on creating a countdown timer in JavaScript that should decrement the value of a field by one every minute (for example, starting at 20 and then changing to 19, 18, 17, and so on). However, I am facing issues with its functionality ...

Issue with retrieving data from an external provider

I'm attempting to fetch data so I can tokenize my Credit Card, but I am required to use this address: this.state.data.CardRegistrationURL == "https://homologation-webpayment.payline.com/webpayment/getToken" Here is my fetch method: postI ...

Populate select2 with the selected value from select1 without the need to refresh the page or click a button

Being a novice in PHP and Javascript, I am looking for a way to populate the "info" select dropdown based on the selected value from the "peoplesnames" dropdown without refreshing the page or using a button. Here's my code: HTML: <select id="peo ...

Ways to show a child's component element within the parent container

Within my Angular 11 project, there exists a component that exhibits a child component containing assorted table filters: Parent Component <table-filters></table-filters> <table> ... </table> Child Component (table-filters) <f ...

How can a color gradient blend be applied to geometry on multiple axes using THREE.JS shader?

After referencing Apply color gradient to material on mesh - three.js I successfully implemented a flower shader that applies a vertical color gradient across the Zinnia. The colors transition from red to yellow vertically, creating a gradient based on he ...

What is a reliable method to retrieve the text from the current LI if all LI elements in the list share the

I'm encountering an issue with retrieving the text from LI elements because I have 10 list items and they all have the same class name. When I attempt to fetch the text using the class name or id, I only get the text of the last item. Here is my code ...

AngularJS: Patience for an asynchronous request

I'm having trouble understanding the concept of promises in AngularJS. Here is a provider I have: var packingProvider = angular.module('packingProvider',[]); packingProvider.provider('packingProvider',function(){ ...

Problem with the render() function in React

I am encountering an issue while trying to retrieve data from an endpoint. A error keeps popping up, mentioning that my render method contains an unexpected token. I would appreciate any assistance. Additionally, I am unsure if I am handling the brackets ...

Looping through data in Vue.js with a specific condition

There is an object structured like this: groupedContacts: { 4: [ {name: 'foo'}, {name: 'bar'} ], 6: [ {name: 'foo bar'}, ] } Additionally, we have another array: companyList.models: models: [ ...

What is the best way to access the methods in the "parent" class?

I am facing a situation where I have an object with fieldsCreators that hold creator methods for each field. The dilemma is how to call the creator method inside fieldsCreators as shown below: var obj={ creator:function(ch) { .... .. ...

How can we automatically delete a message in DiscordJS after a certain amount of time has passed?

I am inquiring about DiscordJS and have a specific question. My query is regarding how to correctly remove a message sent by the bot on Discord. Admittedly, I am new to DiscordJS so please bear with me if this is a basic question. I appreciate all respo ...

In the world of React-Three-Fiber and ThreeJS, the sprite alpha can often appear quite jagged

Currently, I am tackling a project for a client and encountering an issue with transparent logos in threejs. When utilized in the application, these logos exhibit an unattractive dark border that does not align with our desired aesthetic. Despite several a ...

Concurrent execution within a Node.js function

I am facing a challenge with my function that deals with 1400+ crypto pairs. Each pair requires an API call and data storage, resulting in a significant amount of time for the entire process. The bottleneck occurs because each pair takes approximately 3-4 ...

Contrast: Colon vs. Not Equal Sign (Typescript)

Introduction Hello everyone, I am new to Typescript and currently grappling with some fundamental concepts. When defining a parameter for a function, I typically specify the type like this: function example(test: string){...} However, as I delve deeper ...

Employing require.js, one can integrate a distinctive form of non-concatenated dat.gui source. This allows for the seamless

Excuse the SEO-friendly title, but I want to ensure that everyone can access the issue I'm currently working on. For those interested in customizing the appearance of dat.gui, you will need to download the source and include it using require.js follow ...

Ways to capture targeted requests

Utilizing NestJS and Angular 2, I have noticed that both frameworks have a similar approach when it comes to working with Interceptors. I am currently looking for the best practice to identify specific requests in order to perform additional tasks. When d ...

Guide on how to align the bootstrap popover's arrow tip with a text field using CSS and jQuery

I have tried multiple solutions from various questions on Stack Overflow, but I am still struggling to position the arrow tip of the bootstrap popover correctly. html: <input type = "text" id="account_create"/> js: $('.popov ...

Designating a class for the main block

Having an issue with a slider in uikit. When the slide changes, the visible elements also change their class to uk-active. I'm trying to select the central element from the active ones but css nth-child doesn't work. Any suggestions on how to do ...

Error: Attempting to access property 'propeller' of an undefined object has caused a TypeError

I am working on a tutorial that can be found at this link: https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/ During the process, I encountered an error message: Uncaught TypeError: Cannot read property 'propeller& ...