Commit mutation from another file nuxt - vuex

How can I in user.js call mutation from whoToFollow.js called reset ? Is it even possible ? Heres my code:
async logOut({commit}) {
this.$cookies.remove('token');
commit('set_token', null);
commit('whoToFollow/reset');
this.$router.push('/sign-in');
},
But it doesn't work I get this error:
unknown local mutation type: whoToFollow/reset, global type: user/whoToFollow/reset

It is possible to call mutations from other stores directly. You are just missing the option '{root: true}', which is needed for namespaced modules.
I would recommend calling an action in the other store first though, which then again calls the mutations to stay true to the Vuex pattern. Actions -> Mutations
async logOut({commit, dispatch}) {
this.$cookies.remove('token');
commit('set_token', null);
// in the reset action you can then call the commit
dispatch('whoToFollow/reset', payloadHere, { root: true })
this.$router.push('/sign-in');
},
I advise you to check out the Vuex Api Documentation to learn more about this and why you will need 'root: true'.
https://vuex.vuejs.org/api/#vuex-store-instance-methods

Related

Access data from dispatched action using Vuex 4 and Vue 3 Composition API

In my application I have a Vuex 4 store and a Vue 3 Composition Api setup() method.
In the stores action I use axios to make an api call to get a list of bill payments.
The getAllBills action does not live directly in my Store.js file, it exists as a module.
getAllBills({ commit }) {
BillApiCalls.getBills().then(res => {
commit('GET_ALL_BILLS', res.data)
}).catch(error => console.log(error))
},
Then in my Bill.vue file I have the setup() method and am trying to access the data to be used throughout the same Bill.vue file.
setup () {
//Vuex store
const store = useStore();
const billPayments = store.dispatch('payment/getAllBills').then(res => console.log(res));
}
If I check the console from the above .then() res returns as undefined. If I remove the .then() from the billPayments declaration and just do:
console.log(billPayments)
In the console I get
Promise {<pending>}.
Current Store:
import { bill } from './modules/bill.module';
const store = createStore({
modules: {
bill
}
});
The endpoint is working, if I use Postman all of my data is returned as expected but I am having trouble figuring out how to access that data using a dispatched action with the composition api.
The Vuex 4 docs don't mention how to actually resolve the promise to access the data to be used throughout the same component.
An action isn't generally supposed to return data it acts on, data is a part of the state and should be accessed there; this is what another answer shows:
await store.dispatch('payment/getAllBills')
console.log(store.state.payment.bills);
The action doesn't chain promises so it cannot be correctly used. It should be:
return BillApiCalls.getBills()...
Or prefer async..await together with promise to avoid some common mistakes that can be made with raw promises.

Committing a mutation from another module

I would like to reset the state of my stores upon a logout action. I created mutations in each store to reset the state.
I tried doing something like this with no luck.
logout: function ({commit}) {
commit('resetLoginState')
commit('menu.resetMenuState')
}
the logout function is in my login module and the resetMenuState is in another module called menu
Is it possible to do this?
You can use:
commit('path/from/root/to/your/module/menu/resetMenuState', null, { root: true })
you can read more about it on this page

Mutating a state from one module to another Vuex

I'm pretty new to Vuex and am having difficulty understanding how to handle a state change from one module to another. Currently, I have a module called transactions which does an Ajax request and if successful it should close the Modal that is open. I have my modal state set in a separate module called General. I originally tried to set the General State of modal but committing my general mutation closeModal. I realized this won't work and as it sounds like Mutations aren't supposed to do this sort of heavy lifting. I've searched for another method to handle this sort of work and have been lead to Actions but I'm not clear on how to implement it or if it is even supposed to do this kind of work. Would someone please let me know if an Action is the correct method for this problem or if there is another way I should be addressing things.
I have a module called transactions that is running an ajax request and should close a modal if successful. For the sake of this issue, I've simplified my module.
const Transactions = {
state: {
},
mutations: {
CONFIRM_TRANSACTION_CANCEL: function(state) {
this.$store.commit('CLOSE_MODAL')
}
}
And I also have a second module called general which I want to use for general state management and error handling. I'm attempting to call a mutation from transactions into this general module.
const General = {
state: {
modalState: null,
},
mutations: {
...
CLOSE_MODAL: function(state) {
state.modalState = null
},
...
}
}
You should not make a commit inside a mutation. Mutations are only to change the state.
You could do this in two ways:
1.- Using Vue's Watch spying transaction state. Then, if the transaction is correctly done, you dispatch an action to close the Modal.
2.- You can dispatch an action to close the modal inside the action that launches the ajax call (after the success).
apiCall({ dispatch, commit }) {
api.get('/transaction')
.then((response) => {
dispatch('closeModal');
commit('TRANSACTION_SUCCESS', response);
})
.catch((error) => commit('TRANSACTION_ERROR', error));
}
These methods below are done with thinking of the modal as it should use vuex too but, if you want to simplify you can just:
3.- Pass the status of the transaction that comes from vuex directly to the modal by prop and handle the modal with it.

Confused with Vuex commit/dispatch in simple VueJS test

From the book:
To invoke a mutation handler, you need to call store.commit with its type: store.commit('increment')
Mutations must always be synchronous.
From the book:
Actions commit mutations ( can be asynchronous )
Actions are triggered with the store.dispatch method: store.dispatch('increment')
So it's action -> mutation -> new state most of the time.
So what's confusing me, is the very simple example, whereby I'm trying to show the asynchronous result of an object getTest
See this pen
Why can't Vue see that I'm not calling a mutation, but an action when the component loads?
What is this "book" you are talking about? I'm asking because you are using a mix of new Vuex 2.* and old, Vuex 1.* syntax, which is not working anymore in 2.*, so I assume you are learning in part from outdated resources.
(Sidenote: Why are you using Vue 1? Vue2.* has been out for over 10 months now...)
Your action and mutation definitions are correct, but there's no vuex: {} key in components anymore in Vuex 2.*
Also, you are trying to dispatch an action 'INCREMENT', but oyour store only has a mutation by that name, no action. So you have to use commit rather than dispatch.
Instead, you directly add computed props and method to your instance, or use the map*helpers provided by Vuex:
var vm = new Vue({
el: '[vue=app]',
data: {
welcome: 'Testing Vuex'
},
store: myStore,
created() {
this.$store.dispatch(FETCH_TEST_STATE)
},
computed: {
...Vuex.mapState( {
count: state => state.count,
getTest: state => state.testState
}),
}
methods: {
increment({dispatch}) {
this.$store.commit('INCREMENT', 1)
}
}
})
the action you call from created doesn't work because async/await was acting up on codepen
the commit called from this action didn't set any state.
Fixing all of this, here's your working example:
https://codepen.io/LinusBorg/pen/NvRYYy?editors=1010

Is there a way to dispatch actions between two namespaced vuex modules?

Is it possible to dispatch an action between namespaced modules?
E.g. I have Vuex modules "gameboard" and "notification". Each are namespaced. I would like to dispatch an action from the gameboard module in the notification module.
I thought I could use the module name in the dispatch action name like this:
// store/modules/gameboard.js
const actions = {
myaction ({dispatch}) {
...
dispatch('notification/triggerSelfDismissingNotifcation', {...})
}
}
// store/modules/notification.js
const actions = {
triggerSelfDismissingNotification (context, payload) {
...
}
}
But when I try to do this I get errors that make me think Vuex is trying to dispatch an action within my gameboard module:
[vuex] unknown local action type: notification/triggerSelfDismissingNotification, global type: gameboard/notification/triggerSelfDismissingNotification
Is there a way of dispatching actions from a given Vuex module to another, or do I need to create some kind of a bridge in the root Vuex instance?
You just need to specify that you're dispatching from the root context:
// from the gameboard.js vuex module
dispatch('notification/triggerSelfDismissingNotifcation', {...}, {root:true})
Now when the dispatch reaches the root it will have the correct namespace path to the notifications module (relative to the root instance).
This is assuming you're setting namespaced: true on your Vuex store module.
dispatch('mobuleB/actionB', null, { root: true })