Can't dispatch action defined in store sub file - vue.js

In /store/index.js I have:
import Vue from "vue";
import Vuex from "vuex";
import auth from "./modules/auth";
Then in /store/modules/auth.js I have:
export const actions = {
login({ commit, dispatch }, payload) {
...
}
}
But when trying to dispatch my login() action from any component by doing dispatch("auth/login", {}), I get this error:
[vuex] unknown action type: login
Why?
[EDIT] as per Shivam Singh's comment here's my export part:
export default new Vuex.Store({
state: {
token: null
},
getters: {},
mutations: {},
actions: {},
modules: {
auth: {
namespaced: true
}
}
});
After adding auth inside modules: {}, I'm getting this error:
Uncaught TypeError: Cannot read property 'getters' of undefined

/store/modules/auth.js
import Vue from "vue";
import Vuex from "vuex";
import auth from "./modules/auth";
export default new Vuex.Store({
state: {
token: null
},
getters: {},
mutations: {},
actions: {},
modules: {
auth: { // it's registry name, will be used while accessing module content.
namespaced: true,
...auth // actual module content.
}
}
});
While registering the module, you are not providing the actual module
content.
Ref vue doc: https://vuex.vuejs.org/guide/modules.html#namespacing

Related

how to use v model if using vuex

how to use v-model on vuex,
in this case only to show modal box when button is clicked
in this vuex also have separate to module
this is index module
import createPersistedState from 'vuex-persistedstate'
import Vue from 'vue'
import Vuex from 'vuex'
import authentication from './authentication'
import products from './products'
import projects from './projects'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true,
state: {
baseUrl: '/api',
// baseUrl: 'http://localhost:3333/api',
},
mutations: {
},
actions: {
},
modules: {
authentication,
products,
projects,
},
plugins: [
createPersistedState(),
],
})
and this is my module
import HTTP from '../http';
export default {
namespaced: true,
state:{
dialog: false,
},
getters: {
dialog(state){
console.log(state.dialog)
return state.dialog
}
},
mutations: {
closeCard(state){
state.dialog=false;
console.log(state.dialog);
}
}
}
i have try map state and map getter both not function
and this is my vue code
v-model="dialog"
width="500"
i have try use map state or map getter but both not working
import Test from '/components/Test'
export default {
components:{
Test
},
computed: {
dialog:{
get() {
return this.$store.state.dialog.products
},
},
map State('products',[
'dialog'
]),
},
methods:{
map Actions('products',[
'close Card',
])
}
}
and this is my error
Computed property "dialog" was assigned to but it has no setter.
found in
Directly binding a computed property to a v-model is a bad practice as a computed value doesn't have a default setter.
you will need to implement a setter for your computed value. you can read about it here.
you should implement a state action that changes the value of the dialog property and then call it in your setter (and set it to true or false, depending on the case.
Actually there are typo's in your code while called vuex handlers
import {mapState, mapActions } from 'vuex'; // check this line
import Test from '/components/Test'
export default {
components:{
Test
},
computed: {
dialog:{
return this.dialog;
},
...mapState('products',[ // check this line
'dialog'
]),
},
methods:{
...mapActions('products',[ // check this line
'closeCard', // check this line
])
}
}
Also note that you shouldn't directly bind a computed property to a v-model

Vuex access states in actions weird

I have a Vuex store like this. When triggering the storeTest action from my component with this.$store.dispatch("storeTest"); I need to use this weird syntax store.store to access an item.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
loading: false,
fileStr: "data.json",
},
actions: {
storeTest(state) {
//works
console.log("state: ", state.state.fileStr);
//fail
console.log("state: ", state.fileStr);
},
},
},
});
I would expect I can access a state with state.item. Instead I have to write state.state.item. What could be wrong?
It's because actions do not receive state as a parameter, but context. You need it to dispatch other actions or to commit.
actions: {
async myAction ({ state, dispatch, commit }) {
console.log(state.loading);
await dispatch('anotherAction')
commit('someCommit')
}
}
Full list of the context properties here.
The first argument to an action function is not state, rather context (see docs).
This "context" object has various properties, one of which is state.
This differs from a mutation where the first argument is state.
refined and working thanks to #FitzFish
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
loading: false,
fileStr: "data.json",
},
actions: {
storeTest(context) {
//works
console.log("state: ", context.state.fileStr);
},
},
});

How to use non-namespaced and namespaces modules at the same time in Vuex

I'm trying to have a state that consists of namespaced modules and a global state. Unfortunately, I can access the global actions but I can't get the global state properties.
If I try to use mapState in a component like this,
computed: {
...mapState(['editMode']),
...mapState('address', ['addresses']),
}
I have access to addresses, but editMode is always undefined. Mapping actions works flawlessly and updates the state according to the Vuex Chrome Tool.
But I noticed, that the global state is shown under its own "namespace" "global". So I tried to map using ...mapState('global', ['editMode']), but got an error that the namespace does not exist.
Here's my code:
index.ts
import Vue from 'vue';
import Vuex from 'vuex';
import address from './modules/address';
import global from './global';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
address,
global,
},
});
modules/address.ts
export default {
namespaced: true,
state: {
addresses: [],
},
mutations: {
...
},
actions: {
...
},
};
global.ts
export default {
namespaced: false,
state: {
editMode: 0,
},
mutations: {
SET_EDIT_MODE(state, value) {
state.editMode = value;
},
},
actions: {
setEditMode({ commit }, editMode) {
commit('SET_EDIT_MODE', editMode);
},
},
};
State is not affected by namespace. In a way it always gets namespaced. This is so we don't have collision.
To access a state from a module you need to get a bit verbose:
computed: {
...mapState({
editMode: state => state.global.editMode
}),
...mapState('address', ['addresses']),
}

Problem accessing the vuex mutations from inside of the store/index.js

Humbly, I admit that I'm gleaning from SAVuegram in setting up authentication for my app. I am running Firebase's onAuthStateChanged to make certain the user stays logged in during page refreshes however I am completely unable to access the state inside of the function, receiving the following error.
(the $store is just from me taking a screenshot while testing "$store" as well as "store" - both break.)
With strict debugging turned on I'm also getting messages warning me about mutating outside of mutation handlers, but isn't that what I'm doing?
Here's my store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import fb from '../components/firebase/firebaseInit'
import createLogger from 'vuex/dist/logger'
// import dataRefs from './dataRefs'
// import pageTitle from './modules/pageTitle'
import auth from './modules/auth'
import apps from './modules/applicants'
Vue.use(Vuex)
fb.auth.onAuthStateChanged(user => {
if (user) {
// here I can access the user object but never the following "store"
console.log("FB AUTH", user);
store.commit('setCurrentUser', user)
store.dispatch('fetchUserProfile')
}
});
const debug = process.env.NODE_ENV !== 'production'
const createStore = () => {
return new Vuex.Store({
state: {
pageTitle: '',
currentUser: null,
userProfile: null
},
mutations: {
changePageTitle(state, newTitle) {
state.pageTitle = newTitle
},
changeSnackBarMessage(state, newMessage) {
state.snackBarMessage = newMessage
},
// POPUPS
changeAdvisorAddAppPopupStatus(state) {
state.showAdvisorAddPopup = !state.showAdvisorAddPopup
},
setToken(state, token) {
state.token = token;
},
setUser(state, userObj) {
state.user.email = userObj.email;
state.user.fbUUID = userObj.uuid;
}
},
actions: {
updatePageTitle(vuexContext, newTitle) {
vuexContext.commit('changePageTitle', newTitle);
},
updateSnackBarMessage(vuexContext, newMessage) {
vuexContext.commit('changeSnackBarMessage', newMessage);
},
toggleAdvisorAddPopup(vuexContext) {
vuexContext.changeAdvisorAddAppPopupStatus
},
},
modules: {
auth,
apps
},
strict: debug,
plugins: debug ? [createLogger()] : []
})
};
export default createStore;
FYI, I have also tried to instantiate my store by using export const store = new Vuex.Store({ instead of the const create ... method but then Vuex show me that none of my state, actions, getters, or mutations are even found.
Thanks for the help.
Why do you create the store in a function?
const createStore = () => {
I am just doing it like that:
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {
auth,
apps
},
strict: debug,
plugins: debug ? [createLogger()] : []
})
};
export default store;
And i am able to access store now.

Vuex mapstate object undefined and "[vuex] unknown mutation type: "

I'm new with vue.js and vuex and I've an issue with the mapstate object, first I've only one module in my store:
-Store
-index.js
-mutations.js
-actions.js
-state.js
state.js :
export default {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
So when I try to access the userInfo object everything works correctly:
computed: {
...mapState(["userInfo"]),
}
Then I decided to create modules:
-Store
-modules
-ldap.js
-commons.js
-index.js
So the userInfo is in the commons.js file and now when I try to get the object I always get undefined:
commons.js
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
actions,
mutations,
state
}
Component.vue
computed: {
...mapState(["userInfo"]), // <---- undefined
}
main.js :
import Vue from 'vue'
import Vuex from 'vuex'
import commons from './commons'
import ldap from './modules/ldap'
Vue.use(Vuex)
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Can you tell me how to access the userInfo object?
Thanks.
Considering:
Your commons.js is as follows:
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
namespaced: true, // <== make sure this is defined
actions,
mutations,
state
}
And main.js imports it like:
import commons from './commons'
// ..
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Then update on Component.vue:
import { mapState } from 'vuex'
// ...
computed: {
...mapState('commons', ["userInfo"]), // <== add module name here
}
Or
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('commons')
// ... notice module name above ^^^^^^^^^
computed: {
...mapState(["userInfo"]),
}
"[vuex] unknown mutation type: "
Since you are now namespacing your commons module, that modules' mutations now must be prefixed.
So, say you had a mutation like:
const mutations = {
changeName(state, data) {
state.name = data;
}
}
export default {
namespaced: true,
actions,
mutations,
state
}
And you used it like:
this.$store.commit('changeName', "New Name");
Now use it like:
this.$store.commit('commons/changeName', "New Name");
I guess you have namspaced your modules by adding namespaced: true in your module.
So you should pass the module name as the first argument to the mapState helpers so that all bindings are done using that module as the context. See Binding Helpers with Namespace
computed: {
...mapState('commons' , ["userInfo"])
}
You have to define each module as a individual store, here some pseudo example.
// authStore.js
import mutations from './authMutations'
import actions from './authActions'
import getters from './authGetters'
const initialState = {
...
}
export default {
state: initialState,
mutations,
actions,
getters
}
Then, register the modules
import authStore from './authStore'
const store = new Vuex.Store({
modules: {
{...authStore, namespaced: true},
{...postStore, namespaced: true} // some other module defined like auth
}
})
new Vue({
....
store: store
})
And then, on the component use it:
import { createNamespacedHelpers } from 'vuex'
// map state and actions of the module
const { mapState, mapActions } = createNamespacedHelpers('auth')
export default {
computed: {
...mapState({
prop1: 'prop1'
})
}
}
Vuex modules docs
It is really unclear in the documentation but namespaced: true is required to use the map functions.
At least as of the last comment in this discussion
https://github.com/vuejs/vuex/issues/855
Without the need to namespace your modules you can use the callback variant of mapstate:
computed: {
...mapState({
userInfo: state => state.commons.userInfo,
}),
},