vuex duplicate namespace auth/ for the namespaced module auth - vuex

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"
],

Related

Vuex store is inaccessible

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

How to access router from nuxtjs store?

I tried this but only got an error message
This relative module was not found:
* ./router in ./store/index.js
// Ran with yarn dev
import router from './router'
export const state = () => ({
authenticated: false,
})
export const mutations = {
toggleLogin(state, loginStatus, path) {
state.authenticated = loginStatus
if (loginStatus) {
router.push(path)
} else {
router.push('login')
}
},
}
My store path is store/index.js
Vuex mutations and getters doesn't have access to the Vue context. Only actions does.
Also, you can't import the Nuxt router like that. What's that file you're trying to import?
I'd suggest to make an action instead:
export const actions: {
toggleLogin({ commit }, payload) {
this.app.router.push('') //exists
}
}

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.

Issues with registering Vuex modules, either namespaces not found or getters.default is empty

I've been going in circles trying to set up Vuex modules for a project. I've tried following a tweaked example of Chris Fritz example of registering components in a more productive way as seen here: https://www.youtube.com/watch?v=7lpemgMhi0k, but when I try to use ...mapActions, I get issues that the namespace can't be found, if I try to register the modules manually, I get the error that the getter.default expected an action, but returned {}
I'll try keep this clean - the first lot of info is my module setup, the next section is what produces the first issue and the code, the second is the second attempt which produces the getter issue.
My Module setup...
./store/modules/ModuleName:
./store/modules/ModuleName/index.js
import * as actions from './actions'
import * as getters from './getters'
import * as mutations from './mutations'
const namespaced = true
export default {
namespaced,
state () {
return {
foo: 'bar'
}
},
actions,
getters,
mutations
}
./store/modules/ModuleName/actions.js
import types from './types'
const myFunction = ({ commit, state }) => {
commit(types.FOO, bar)
}
export default {
myFunction
}
./store/modules/ModuleName/getters.js
const Foo = (state) => {
return state.foo
}
export default {
Foo
}
./store/modules/ModuleName/mutations.js
import types from './types'
const mutateFoo = (state, payload) => {
state.Foo = payload
}
export default {
[types.FOO]: mutateFoo
}
./store/modules/ModuleName/types.js
export default {
FOO: 'foo'
}
Version one
This is the preferred way I'd like to do it:
Error: [vuex] module namespace not found in mapActions(): myModule/
./store/modules.js
const requireModule = require.context('../store/modules/', true, /\.js$/)
const modules = {}
requireModule.keys().forEach(fileName => {
// Use index to prevent duplicates of the same module folder...
if (fileName.includes('index')) {
// now I just want the folder name for the module registration
const moduleName = fileName.replace(/(\.\/|\/.+\.js)/g, '')
modules[moduleName] = requireModule(fileName)
}
})
export default modules
./store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules
})
.Vue component:
<template>
...
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState('ModuleName', { title: state => state.foo })
},
methods: {
...mapActions('ModuleName, ['myFunction'])
}
}
</script>
Version Two
Error:
Uncaught Error: [vuex] getters should be function but
"getters.default" in module "Harvest" is {}.
./store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import Harvest from './modules/myModule'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
myModule
}
})
.Vue component:
<template>
...
</template>
<script>
export default {
computed: {
title () { return this.$store.getters.myModule }
}
}
</script>
What am I missing? Can someone help shed a bit of light to get this working?
For your Version two, because you export default, your import state should be:
import actions from './actions'
import getters from './getters'
import mutations from './mutations'
const namespaced = true
export default {
namespaced,
state () {
return {
foo: 'bar'
}
},
actions,
getters,
mutations
}
For version 1, first you should change import statement as above, then change
if (fileName.includes('index')) {
// now I just want the folder name for the module registration
const moduleName = fileName.replace(/(\.\/|\/.+\.js)/g, '')
modules[moduleName] = requireModule(fileName).default
}
Hope it can help!

Access the state of store or getters? _WEBPACK_IMPORTED_MODULE_3__store___.a.dispatch is not a function

I am trying to verify if the user is authenticated to be able to give access to the route that is directed otherwise redirect to the login route, the problem is that I do not know how to execute the fetchUser action from my beforeEach. In other words, I can't access my getter from the router script.
store.js
import mutations from './mutations';
import actions from './actions';
import getters from './getters';
export default {
state: {
isLoggedIn: !!localStorage.getItem("token"),
user_data : localStorage.getItem("user_data"),
},
getters ,
mutations,
actions
}
routes/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import routes from './rutas';
import store from '../store/';
const router = new VueRouter({
mode : 'history',
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!store.getters.isLoggedIn) {
next({path: '/login'})
}
else {
store.dispatch('fetchUser') // Line error
next()
}
}
else {
next() // make sure to always call next()!
}
})
getters.js
export default {
isLoggedIn: state => {
return state.isLoggedIn
},
user_name : state =>{
if(! _.isEmpty(this.user_data))
return JSON.parse(state.user_data).name
return '';
},
isEmptyUser : state =>{
return _.isEmpty(this.user_data);
},
isAdmin: state => {
if(! _.isEmpty(this.user_data)) return state.user_data.nivel===1
return false;
}
}
actions.js
export default {
/* more methods*/
, async fetchUser({ commit }) {
return await axios.post('/api/auth/me')
.then(res => {
setTimeout(() => {
localStorage.setItem("user_data", JSON.stringify(res.data));
Promise.resolve(res.data);
}, 1000);
},
error => {
Promise.reject(error);
});
}
This returns error in console:
_WEBPACK_IMPORTED_MODULE_3__store___.a.dispatch is not a function
How can I do or the approach is the wrong one and I should not access actions directly?
The problem is your store is not the actual store object, it is just the object used to generate it.
A solution is to have the file export the real store:
import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations';
import actions from './actions';
import getters from './getters';
Vue.use(Vuex); // added here
export default new Vuex.Store({ // changed here
state: {
isLoggedIn: !!localStorage.getItem("token"),
user_data : localStorage.getItem("user_data"),
},
getters ,
mutations,
actions
}) // changed here
Now your router code would work.
What you must be aware as well is that somewhere, probably in your main.js, you had the store being initialized like above. For example:
import store from '../store/';
new Vue({
store: new Vuex.Store(store),
// ...
})
Now you must remove that initialization and use the store directly:
import store from '../store/';
new Vue({
store: store, // or simply store
// ...
})
And all should be good.