Change another module state from one module in Vuex
Asked Answered
T

5

118

I have two modules in my vuex store.

var store = new Vuex.Store({
    modules: {
        loading: loading 
        posts: posts
    }
});

In the module loading, I have a property saving which can be set either true or false and also have a mutation function named TOGGLE_SAVING to set this property.

In the module posts, before and after fetching posts, I want to change the property saving. I am doing it by calling commit('TOGGLE_SAVING') from one of the actions in the posts module.

var getPosts = function (context) {
    context.commit(TOGGLE_LOADING);
};

When it tried to commit, I got following error in the console

[vuex] unknown local mutation type: TOGGLE_LOADING, global type: posts/TOGGLE_LOADING 

How can I mutate state in another module using commit?

Typhoon answered 5/3, 2017 at 8:21 Comment(1)
If you are getting a response from lets say an api you will use commit('loading/TOGGLE_LOADING', response.data, {root: true})Cirrhosis
T
229

Try it with following parameters as suggested here;

commit('TOGGLE_LOADING', null, { root: true })

If you have namespaced set to true (in Nuxt that's the default when in modules mode), this becomes:

commit('loading/TOGGLE_LOADING', null, { root: true })
Tricksy answered 5/3, 2017 at 9:50 Comment(7)
If you're using modules and namespaces, don't forget to add the namespace to the commit, like commit('namespace/TOGGLE_SAVING', null, { root: true }) or else it won't work.Ottie
This doesn't work for me. I just get 'unknown mutation type'.Endue
I had a similar need and your answered solved my probelm. Thank you.Radiance
Why is root: true needed for this, was sure Nuxt should be able to figure find the other module's mutations?Starspangled
@Starspangled I know this is a late answer, but… {root: true} is necessary to indicate that the path is root-relative (i.e., as it appears) and not relative to the current module. Nuxt knows you're using modules, but that doesn't absolve you from having to provide, in effect, fully qualified pathsEphah
does captal matter?Drye
@Endue I got the same thing because I ignored the { root: true } part. Once adding that in it worked like a dream. I suspect that means the path of the namespace starts from root instead of being appended to the current namespace...Impugn
C
3

If you have used namespaced: true in your modules, there are two ways for it:

1- you should add { root: true }:

commit('TOGGLE_LOADING', null, { root: true }) 

2- define a global action as below (e.g. globalToggleLoading) and call it from any modules you want by dispatch('globalToggleLoading')

globalToggleLoading: {
    root: true,
    handler({ commit }) {
      commit('TOGGLE_LOADING')
    }
  }

If your modules are not namespaced, you can call any mutations or actions by calling commit, dispatch:

commit('TOGGLE_LOADING')
Cultivable answered 21/8, 2021 at 18:23 Comment(0)
M
2

you can use action to commit mutation which defined in another module,then you will modify state in another module.

like this:

posts: {
  actions: {
    toggleSavingActions(context) {
      // some actions 
      context.commit("TOGGLE_SAVING"); // defined in loading module
    }
  }
}
Mattress answered 5/3, 2017 at 9:26 Comment(4)
This is how exactly I have done it. I also set "namespace: true" in both modules. But i am getting [vuex] unknown local mutation type: TOGGLE_LOADING, global type: posts/TOGGLE_LOADINGTyphoon
oh yes.by default, actions, mutations and getters inside modules are still registered under the global namespace .so you can either remove namespace property,or use commit('someMutation', null, { root: true })Mattress
In my case if I use namespace: true, I need to do the next: commit('my_module_name/someMutation', null, { root: true })Carnarvon
A commit is synchronous while an action is asynchronous so afaik you should not use an action to commit a mutation.Phosphorus
S
2

You can also import the store, as you normally do in any js file and use it. For example:

// src/state/modules/posts.js

import store from '@/state/store'
...
store.commit('posts/TOGGLE_LOADING')
...

This works pretty well, the only donwside is that can difficult isolate tests or mock-up.


Edition: Recently I have eliminated all code using the technique I mention due the testing problems. Indeed you can always change the state of other modules following the recommended way, as in this example. Very useful if you manage auth and profile in distincts modules.

logout: context => {
  return new Promise((resolve) => {
    // Clear token in all axios requests
    axios.defaults.headers.common['Authorization'] = ''
    // Logout from firebase
    firebase
      .auth()
      .signOut()
      .then(() => {
        // Update state in profile module
        context.commit('profile/SET_USER', null, {
          root: true
        })
        resolve()
      })
      .catch(error => reject(error))
  })
}
Sharolynsharon answered 29/5, 2020 at 23:46 Comment(1)
adding null + setting root true works indeed. Was wondering why this is necessary at all? nuxt should be able to figure out where external commit resides?Starspangled
G
0

Using: Named modules, I had the same problem:

unknown mutation type

I have a common module : commonModule.js

import store from '../../';
const SET_ERROR   = 'SET_ERROR'

export default {
    state: () => ({
      error: [],
    }),
    mutations: {
        [SET_ERROR] (state, payload){
            state.error = payload
        },
    },
    actions: {
      setError ({ commit }, error) {
        commit(SET_ERROR, error)
      },
    },
}

Then in all other modules I had to call set error, so I called like this, which is error:

commit('setError', 'Socket is not defined!')

later I changed to this, which in my case solved the problem:

commit('SET_ERROR', 'Socket is not defined!')

I later deleted:

namespace: true,

This form is not working:

commit('commonModule/SET_ERROR', 'Socket is not defined!')

nor this one:

commit('commonModule/setError', 'Socket is not defined!')

hope to be useful.

Gunk answered 28/8, 2023 at 19:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.