Vuex store is inaccessible - vue.js

I made a vuex store:
export const general = {
namespaced: true,
state: {
menuEnabled: true,
headerEnabled: true
},
getters: {
menuState: state => state.menuEnabled,
headerState: state => state.headerEnabled
},
actions: {
setMenuVisibility({commit}, visibility) {
commit('setMenuVisibility', visibility);
},
setHeaderVisibility({commit}, visibility) {
commit('setHeaderVisibility', visibility);
}
},
mutations: {
setMenuVisibility(state, visibility){
state.menuEnabled = visibility;
},
setHeaderVisibility(state, visibility){
state.headerEnabled = visibility;
}
}
}
index.js
import { createStore } from "vuex";
import { auth } from "./auth.module";
import {general} from "./general.module";
const store = createStore({
modules: {
general,
auth
},
});
export default store;
main.js
import router from "./router";
import store from "./store";
createApp(App)
.use(store)
.use(router)
.mount('#app')
After that, I created 2 computed functions in App.vue:
computed: {
menuVisibilityState : function (){
return this.$store.state.menuEnabled;
},
headersVisibilityState : function () {
return this.$store.state.headerEnabled;
}
}
But, I can't get them from vuex:
I tried to import general directly in App.vue and get the values.
It doesn't work and I think, that it's bad way to get them.
Can somebody help me?

When you create a module in Vuex, the local state is nested depending on the name you've provided to the module (this happens when you're accessing the root state.).
In your example, to access the local state of general module you could write:
computed: {
menuVisibilityState : function (){
return this.$store.state.general.menuEnabled;
},
headersVisibilityState : function () {
return this.$store.state.general.headerEnabled;
}
}
Keep in mind that:
actions and mutations are still registered under the global namespace - this allows multiple modules to react to the same action/mutation type. Getters are also registered in the global namespace by default.
https://vuex.vuejs.org/guide/modules.html#namespacing

Related

Modules vs Multiple vuex store files

I am working on a project using vue and vuex. And I think most of the people are having the problem, after sometime the store.js (or index.js) is getting too big. So I want to split the store.js file. After some google I found I can use Modules to overcome this problem. BUT I tried also with creating a new Instance of vuex and it works perfectly fine.
Single instance with modules :
---store.js
import Vuex from "vuex";
import thisismodule1 from "./modules/module1";
import thisismodule2 from "./modules/module2";
const createStore = () => {
return new Vuex.Store({
modules: {
module1: thisismodule1,
module2: thisismodule2
}
});
};
export default createStore;
const store = new Vuex.Store({
module
});
Multiple files with multiple instances:
---storeCar.js
---storeHouse.js
---storeTree.js
...
So my question is, is this allowed or do I have to use modules with single instance?
Thank you in advance!
there is a best practice for that:
Create a file. that's name is Shared
Create a Store folder and create a modules folder on it:
you should modules in the modules folder and define your store for a target:
for example:
import * as types from "../types";
const state = {
currentPage: {}
};
const getters = {
[types.avatarManagement.getters.AVATAR_MANAGEMENT_GET]: state => {
return state.currentPage;
}
};
const mutations = {
[types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE]: (
state,
payload
) => {
state.currentPage = payload;
}
};
const actions = {
[types.avatarManagement.actions.AVATAR_MANAGEMENT_ACTION]: (
{ commit },
payload
) => {
commit(types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE, payload);
}
};
export default {
state,
getters,
mutations,
actions
};
Create index.js for define Vuex and import your modules:
index.js file:
import Vue from "vue";
import Vuex from "vuex";
import avatarManagement from "./modules/avatarManagement";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
avatarManagement
}
});
5) also you can types of your vuex store on Type.js file:
type.js:
export const avatarManagement = {
getters: {
AVATAR_MANAGEMENT_GET: "AVATAR_MANAGEMENT_GET"
},
mutations: {
AVATAR_MANAGEMENT_MUTATE: "AVATAR_MANAGEMENT_MUTATE"
},
actions: {
AVATAR_MANAGEMENT_ACTION: "AVATAR_MANAGEMENT_ACTION"
}
};
***for get data from Store:
computed: {
...mapGetters({
registrationData:types.avatarManagement.AVATAR_MANAGEMENT_GET,
getDataFromStore() {
return this.registrationData;
}
}
***for Change data to Store and mutate that:
methods: {
goToActivity() {
const activity = {
companyList: this.categories
};
this.$store.commit(types.avatarManagement.AVATAR_MANAGEMENT_MUTATE, {
newData
});
},
}

vuex duplicate namespace auth/ for the namespaced module auth

I am using nuxt.js with the auth module.
Every time i open a new page on my profile this error message appears.
I have created a mixin called auth.js in my plugins/mixins directory. This file contains the code:
export const getters = {
authenticated(state) {
return state.loggedIn;
},
user(state){
return state.user;
}
};
I've created a getter file called auth.js with the following code:
import Vue from 'vue'
import {mapGetters} from 'vuex'
const User = {
install(Vue, options) {
Vue.mixin({
computed: {
...mapGetters({
user: 'auth/user',
authenticated: 'auth/authenticated'
})
}
})
}
};
Vue.use(User);
The getters and mixin work, but everytime i open a page it gives me this error and i dont know how to solve it. I've tried the solutions in this question:
duplicate namespace auth/ for the namespaced module auth
Altough this does solve the errors, it makes my getters undefined.
Yeah, I found a workable way ...
Switch to index.js auth.js logic, and delete auth.js.
index.js
export const getters = {
authenticated(state) {
return state.auth.loggedIn
},
user(state) {
return state.auth.user
}
}
Revise it as follows if you are using a user.js mixin:
import Vue from 'vue'
import {mapGetters} from 'vuex'
const User = {
install(Vue, options) {
Vue.mixin({
computed: {
...mapGetters({
user: 'user',
authenticated: 'authenticated'
})
}
})
}
};
Vue.use(User);
Plugins:
** Plugins to load before mounting the App
*/
plugins: ["./plugins/mixins/user.js"
],

vuex unknown action type when attempting to dispatch action from vuejs component

I'm using laravel, vue and vuex in another project with almost identical code and it's working great. I'm trying to adapt what I've done there to this project, using that code as boilerplate but I keep getting the error:
[vuex] unknown action type: panels/GET_PANEL
I have an index.js in the store directory which then imports namespaced store modules, to keep things tidy:
import Vue from "vue";
import Vuex from "vuex";
var axios = require("axios");
import users from "./users";
import subscriptions from "./subscriptions";
import blocks from "./blocks";
import panels from "./panels";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
actions: {
},
mutations: {
},
modules: {
users,
subscriptions,
blocks,
panels
}
})
panels.js:
const state = {
panel: []
}
const getters = {
}
const actions = {
GET_PANEL : async ({ state, commit }, panel_id) => {
let { data } = await axios.get('/api/panel/'+panel_id)
commit('SET_PANEL', data)
}
}
const mutations = {
SET_PANEL (state, panel) {
state.panel = panel
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Below is the script section from my vue component:
<script>
import { mapState, mapActions } from "vuex";
export default {
data () {
return {
}
},
mounted() {
this.$store.dispatch('panels/GET_PANEL', 6)
},
computed:
mapState({
panel: state => state.panels.panel
}),
methods: {
...mapActions([
"panels/GET_PANEL"
])
}
}
</script>
And here is the relevant code from my app.js:
import Vue from 'vue';
import Vuex from 'vuex'
import store from './store';
Vue.use(Vuex)
const app = new Vue({
store: store,
}).$mount('#bsrwrap')
UPDATE:: I've tried to just log the initial state from vuex and I get: Error in mounted hook: "ReferenceError: panel is not defined. I tried creating another, very basic components using another module store, no luck there either. I checked my vuex version, 3.1.0, the latest. Seems to be something in the app.js or store, since the problem persists across multiple modules.
Once you have namespaced module use the following mapping:
...mapActions("panels", ["GET_PANEL"])
Where first argument is module's namespace and second is array of actions to map.

How to get the latest updated data on VueJs?

I'm new to Vuejs and still figuring out how to get the latest updated data.
app.js - preload the data after calling 'global/checkUserSignedIn'
import Vue from 'vue'
import axios from 'axios'
import router from './router'
import store from './store'
import { sync } from 'vuex-router-sync'
import App from 'components/app-root'
import { mapGetters, mapActions } from 'vuex'
Vue.prototype.$http = axios
sync(store, router)
const app = new Vue({
store,
router,
...App,
created() {
this.preload()
},
methods: {
preload: function () {
this.$store.dispatch('global/checkUserSignedIn')
}
}
})
export { app, router, store }
global.js (a vuex store)
/// actions, mutations here
const actions = {
checkUserSignedIn({ commit, state }) {
commonApi.isUserSignedIn().then(function (data) {
state.usersignedin = data
})
},
}
const getters = {
isUserSignedIn: state=>state.usersignedin
}
export default {
state,
getters,
actions,
mutations,
namespaced: true
}
On a component, I call:
export default {
computed: {
...mapGetters('global', ['isUserSignedIn']),
},
watch: {
isUserSignedIn: function (newVal, oldVal) {
if (newVal !== undefined) {
console.log('ok, correct result')
}
}
},
updated() {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
console.log('updated: ' + this.isUserSignedIn)
})
},
created() {
console.log('created :' this.isUserSignedIn)
}
}
}
On both Updated and Created, I don't get the last updated data isUserSignedIn which is True if a user has been logged in though if I put {{isUserSignedIn }} on a template, it shows correctly.
Is there any way to get it to work other than having to use a Watcher here.
Updated: Maybe using Watcher is the only way to get the lastest updated data.

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,
}),
},