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

ReactJS - What makes ReactJS unique compared to other technologies?

Hey there! I'm currently trying to figure out why this specific code snippet was successful while my previous one wasn't. I've included both snippets below: SUCCESSFUL CODE: handleInputChange = (e) => { let { value } = e.target; ...

Utilizing external functions in Node.js by importing them from different files

Struggling to import methods from my ./db/index.js into my server.js file in order to retrieve data from the database and show it. The content of /db/index.js is as follows: 'use strict'; const pgp = require('pg-promise')(); const pg ...

What is the best way to fully eliminate the Pixi renderer, stage, and all associated assets

I am currently faced with a challenge of mounting and unmounting a Pixi stage using React without relying on react-pixi. Upon re-mounting the component, I encounter the following error: Uncaught Error: Resource with name "cupCake.png" already exists i.ad ...

Navigation menu with submenus containing buttons

I attempted to incorporate a dropdown into my existing navigation bar, but unfortunately, the dropdown content disappeared after adding the necessary code. I am now at a loss on how to troubleshoot this issue and make the dropdown function properly. Despit ...

Capture XMLHttpRequest request and manually send a 200 status response using vanilla JavaScript

After extensive research, I found conflicting information on this topic. I need to intercept an XMLHttpRequest and simulate a 200 status response from the backend using plain Javascript. This is specifically for testing purposes. So far, I have made pro ...

Emulate a link click using key input

Hey there! I have this link example: <a href"http://google.es">Link</a> I'm wondering if it's possible to use JavaScript or a similar tool so that when I press a specific key, like the number 5 on the keyboard, it acts as if I click ...

Encountering the issue of "TypeError: Cannot read property 'file' of undefined" when trying to upload a video with Multer

The objective is to select a video file from the desktop and upload it to the platform. The uploaded video file will then be automatically posted to a specified Youtube channel using GCD. An error message I encountered is:"react-dom.development.js:40 ...

Troubleshooting: How to resolve the issue of "Error [ERR_HTTP_HEADERS_SENT]: Unable to set headers after they have been sent to the client"

* **> const PORT=8000 const express = require('express') const {v4:uuidv4}=require('uuid') const bcrypt =require('bcrypt') const jwt =require('jsonwebtoken') const cors=require('cors') const {MongoClie ...

Having trouble viewing the image slider on an HTML webpage

I've been attempting to incorporate an image slider into my personal website on GitHub, but I've encountered some difficulties as the images are not displaying. Interestingly, I can load individual images without using the slider and they show up ...

How to Properly Implement app.use() in Express for Middleware

What is the reason behind some middleware functions being passed in with invocation parentheses, while an anonymous function is passed in without being invoked? app.use(logger()); app.use(bodyParser()); If logger() is evaluated immediately and the return ...

The radio button that disables other inputs only functions correctly for a single element when using Query Selector, but does not work with Query

I have attempted to develop a form section that is disabled when the user selects option A and enabled when they choose option B. document.getElementById('delivery').onclick = function() { var disabled = document.querySelectorAll(".dis ...

Utilize key-value pairs to reference variables when importing as a namespace

Is it feasible to utilize a string for performing a lookup on an imported namespace, or am I approaching this the wrong way? Consider a file named my_file.ts with contents similar to: export const MyThing: CustomType = { propertyOne: "name", ...

Utilizing query parameters in Next.js

I've been working on a unique Next.js application that incorporates both infinite scroll and a search input feature. The infinite scroll functionality loads 6 additional items whenever the user reaches the bottom of the page. On the other hand, the s ...

Vite build error: TypeError - Unable to access properties of null while trying to read 'useContext'

I used the following component imported from material-ui : import Paper from '@mui/material/Paper'; After running npm run build followed by npm run preview, I encountered an error in the console: Uncaught TypeError: Cannot read properties of n ...

When working with NodeJS and an HTML form, I encountered an issue where the 'Endpoint'

Having trouble sending input data from a form to my nodejs endpoint. When I try printing the req.body, it shows up as undefined and I can't figure out why. Here is the relevant API code snippet: var bodyParser = require('body-parser') var e ...

Make sure that JSON.stringify is set to automatically encode the forward slash character as `/`

In my current project, I am developing a service using nodejs to replace an old system written in .NET. This new service exposes a JSON API, and one of the API calls returns a date. In the Microsoft date format for JSON, the timestamp is represented as 159 ...

"Implementing a click event on a dynamically generated element is triggering the event for all of its parent elements

I have a task to generate a dynamic table with data retrieved from the server. Each row in the table contains a tag that I am trying to link to a click event. The code snippet below demonstrates how the dynamic table is created: function ProcessResponse ...

There seems to be an issue with Ajax functionality within the Webix framework

Exploring webix for the first time has been quite an interesting journey. I am carefully following the guidance provided in the getting started document to create my own webix program. By placing my code in an HTML page and two JSON files as instructed, he ...

Building on the Vuejs3 and Vuex4 framework, create a conditional rendering feature that triggers upon

I have a unique setup where custom objects are used to hold child objects full of data. The child objects start with null values for all properties, allowing them to be filled with data from remote sources when referenced. This results in a lazy-loading sy ...

"Step-by-step guide on assigning a class to a Component that has been

When attempting to pass a component as a prop of another component, it functions correctly. However, when I try to pass a Component and manage its CSS classes within the children, I find myself stuck. I am envisioning something like this: import Navbar fr ...