vueX with vuei18n. this.dispatch is not able to access vuei18n - javascript

I am relatively new to Vue and I've been reading the documentation and forums for quite a while for a solution to this one but haven't found it yet.
I am using the Vue Webpack template: here
I'm trying to create an app where I have an API endpoint to get the currency and country for the user as well as the user language from the browser.
I am using this.$store.dispatch('setlanguage') on initialisation of the Vue Component to set the state of the language, and save it to a cookie. The problem here though is that I am unable to alter the vuei18n as my app says it does not exist. The reason I am using vuei18n instead of vueXi18n is because the latter does not have the numberFormat options and this is needed in order to set correctly the currency symbols.
So to get things started:
Project structure:
main.js
App.Vue
store
getters.js
index.js
mutation-types.js
mutations.js
router
index.js
lang
locales
en.js
fr.js
de.js
lang.js
components
LocaleSwitcher.vue
pages
Footer.vue
Home.vue
main.js
import Vue from 'vue'
import VueResource from 'vue-resource'
import Cookies from 'js-cookie'
import App from './App.vue'
import i18n from './lang/lang'
import store from './store'
import router from './router'
Vue.use(VueResource)
Vue.config.productionTip = false
Vue.config.language = Cookies.get('lang')
Vue.config.country = Cookies.get('country')
Vue.config.currency = Cookies.get('cur')
export const localeStrings = {
en: 'English',
de: 'Deutsch',
fr: 'Français',
it: 'Italiano',
nl: 'Nederlands',
sv: 'Svenska',
es: 'Español',
ja: '日本語'
}
export const app = new Vue({
el: '#app',
router,
store,
i18n: i18n,
render: h => h(App),
created () {
this.$store.dispatch('setLang', Vue.config.language)
this.$store.dispatch('setCountry', Vue.config.country)
}
})
lang.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
let i18n = new VueI18n({
locale: 'en',
messages: {},
fallbackLocale: 'en',
numberFormats: {}
})
export default {i18n}
App.vue
template>
<div id="app">
<app-header></app-header>
<div class="main-content">
<router-view></router-view>
</div>
<app-footer></app-footer>
</div>
</template>
<script>
export default {
name: 'myapp',
components: {
'app-footer': Footer
},
data () {
return {
msg: 'Welcome to Your Vue.js App',
language: ''
}
}
}
<style>
body {
margin:0;
padding:0;
}
</style>
Home.vue
<template>
<h1>Hello Home! {{msg}}</h1>
</template>
<script>
export default {
data () {
return {
msg: 'Home msg'
}
}
}
</script>
<style scoped>
h1 {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
}
</style>
Footer.vue
<template>
<footer>
<p>{{copyright}}</p>
<local-switcher></local-switcher>
</footer>
</template>
<script>
import LocaleSwitcher from '../components/LocaleSwitcher.vue'
export default {
name: 'Footer',
components: {
'local-switcher': LocaleSwitcher
},
data () {
return {
copyright: 'Copyright 2018 Francesco'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
footer{
background: lightgrey;
padding: 10px;
}
</style>
LocaleSwitcher.vue
<template>
<div class="locale-switcher">
<select v-model="activeLocale" #change="changeLang">
<option v-for="(lang, id) in locales" :key="id" v-bind:value="id">{{lang}}</option>
</select>
</div>
</template>
<script>
import {localeStrings} from '../main'
export default {
name: 'locale-switcher',
data: function () {
return {
activeLocale: this.$store.getters.getLanguage,
locales: localeStrings
}
},
methods: {
changeLang () {
this.setLang(this.activeLocale)
},
setLang (lang) {
this.$store.dispatch('setLang', lang)
}
}
}
</script>
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import p404 from '../pages/error/404.vue'
import Home from '../pages/Home.vue'
Vue.use(Router)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '*',
name: '404',
component: p404
}
]
let router = new Router({
mode: 'history',
routes
})
// I still have to figure out how to use this to set www.mypage.com/mylanguage/home
// use beforeEach route guard to set the language
router.beforeEach((to, from, next) => {
// use the language from the routing param or default language
let language = to.params.lang
console.log(language)
console.log('router end')
if (!language) {
language = 'en'
}
// set the current language for vuex-i18n. note that translation data
// for the language might need to be loaded first
// Vue.i18n.set(language)
next()
})
export default router
store/getters.js
export const getters = {
getLanguage: state => {
return state.language
},
getCountry: state => {
return state.country
},
getCurrency: state => {
return state.currency
}
}
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { state, mutations, actions } from './mutations'
import { getters } from './getters'
Vue.use(Vuex)
// const mapState = Vuex.mapState
const store = new Vuex.Store({
state,
mutations,
actions,
getters
})
export default store
store/mutation-types.js
export const SET_LANG = 'SET_LANG'
export const SET_COUNTRY = 'SET_COUNTRY'
export const SET_CURRENCY = 'SET_CURRENCY'
store/mutations.js
import Vue from 'vue'
import Cookies from 'js-cookie'
import * as types from './mutation-types'
import {app, supportedLocale, supportedCurrencies} from '../main'
import CountryCurrency from '../data/country_currency.json'
import locale2 from 'locale2'
export const state = {
language: Cookies.get(settings.languageCookie),
country: Cookies.get(settings.countryCookie),
currency: Cookies.get(settings.currencyCookie),
loading: false
}
export const mutations = {
[types.SET_LANG] (state, payload) {
Cookies.set('lang', payload)
state.language = payload
},
[types.SET_COUNTRY] (state, payload) {
Cookies.set('country', payload)
state.country = payload
},
[types.SET_CURRENCY] (state, payload) {
Cookies.set('currency', payload)
state.currency = payload
}
}
export const actions = {
async setLang ({commit}, language) {
console.log(app)
console.log(Vue)
var vueMessages = app.$i18n.messages
var userLocale = 'en'
var browserLocale = locale2.split('-', 1)[0]
// testing browser language
if (locale === undefined) {
// get browser language
userLocale = browserLocale
} else if (browserLocale !== locale) {
console.log('browser language changed')
userLocale = browserLocale
} else {
userLocale = locale
}
// check for supported languages
if (!supportedLocale.includes(userLocale)) {
userLocale = 'en'
}
if (language in vueMessages) {
console.log('already in messages')
commit(types.SET_LANG, language)
} else if (!supportedLocale.includes(language)) {
console.log('not supported so commiting default en')
commit(types.SET_LANG, 'en')
} else {
try {
// you can use fetch or import which ever you want.
// Just make sure your webpack support import syntax
// const res = await axios.get(`./src/lang/${payload}.json`)
const res = await import(`../lang/locales/${language}.json`)
app.$i18n.locale = language
app.$i18n.setLocaleMessage(language, res)
var addNumberFormats = {
currency: {
style: 'currency', currencyDisplay: 'symbol', currency: `${app.$i18n.currency}`
}
}
app.$i18n.mergeNumberFormat(language, addNumberFormats)
Cookies.set('lang', language)
commit(types.SET_LANG, language)
} catch (e) {
console.log(e)
}
}
},
setCountry ({commit}, countryCode) {
var userCountry = 'NA'
if (countryCode === undefined || countryCode === 'NA') {
Vue.http.get('https://www.myapi.com/api/v2/geo/country-code', {
timeout: 100
}).then(response => {
state.country = response.data.code
Cookies.set('country', response.data.code)
}, response => {
// error callback
state.country = userCountry
Cookies.set('country', userCountry)
})
} else {
console.log(countryCode)
state.country = countryCode
Cookies.set('country', countryCode)
}
},
setCurrency ({commit}, countryCode) {
var userCurrency = 'USD'
console.log('user country ' + countryCode)
console.log('user currency ' + CountryCurrency[countryCode])
console.log('currency supported: ' + supportedCurrencies.includes(CountryCurrency[countryCode]))
if (CountryCurrency[countryCode] && supportedCurrencies.includes(CountryCurrency[countryCode])) {
userCurrency = CountryCurrency[countryCode]
}
Cookies.set('currency', userCurrency)
app.$i18n.currency = userCurrency
try {
var addNumberFormats = {
currency: {
style: 'currency', currencyDisplay: 'symbol', currency: `${app.$i18n.currency}`
}
}
if (!app.$i18n.numberFormats[app.$i18n.locale]) {
console.log('merge currency')
app.$i18n.setNumberFormat(app.$i18n.locale, addNumberFormats)
}
} catch (error) {
console.log(error)
}
}
}
The problem is that once loaded, I cannot access the app vue i18n. Am I accessing it incorrectly or is there another way to add language and currency settings to this? I hope I have provided enough info Thanks!

Could this answer be relevant in your case? https://stackoverflow.com/a/45460729/2964531
If you need to access or mutate properties of i18n, you can import it directly from store/mutations.js

Related

Vuex is not able to find namespace of module

I have a Vue2 sample app and want to add a Vuex store with a todos module. Inside the store folder I changed the index.js file to
import Vue from "vue";
import Vuex from "vuex";
import * as todos from "./modules/todos/index.js";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
todos
},
});
Inside
/store/modules/todos
I created the following files
index.js
import * as state from "./state.js";
import * as getters from "./getters.js";
export const module = {
namespaced: true,
state,
getters,
};
state.js
export const state = {
todos: []
}
getters.js
export const getters = {
todos(state) {
return state.todos;
}
};
Inside my component I want to access the getter:
<script>
import { mapGetters } from "vuex";
export default {
computed: {
...mapGetters("todos", ["todos"]), // namespace.getter
},
};
</script>
Unfortunately I get this error when loading the component
[vuex] module namespace not found in mapGetters(): todos/
Does someone know what's wrong or missing here? Thanks for help
I think your import/export statements are the culprit.
Try this:
/store.js
import Vue from "vue";
import Vuex from "vuex";
import todos from "./modules/todos";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
todos
},
});
/store/modules/todos/index.js
import state from "./state";
import getters from "./getters";
const todos = {
namespaced: true,
state,
getters,
};
export default todos;
The other files seem fine.
Work for me
Base API URL
project/src/api/common.js
import axios from 'axios'
export const HTTP = axios.create({
baseURL: 'http://api-url',
})
Base element project/src/api/element.js
import {HTTP} from './common'
function createHTTP(url) {
return {
async post(config) {
return HTTP.post(`${url}`, config).then(response => {
console.log(response)
return response.data
})
},
async get(element) {
return HTTP.get(`${url}${element.id}/`)
},
async patch(element) {
console.log(element)
return HTTP.patch(`${url}${element.id}/`, element).then(response => {
console.log(response)
return response.data
})
},
async delete(id) {
HTTP.delete(`${url}${id}/`)
return id
},
async list(queryParams = '') {
return HTTP.get(`${url}${queryParams}`).then(response => {
return response.data.results
})
}
}
}
export const Todos = createHTTP(`/todos/`)
Your store project/src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import todos from "#/store/modulse/todos";
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
todos,
}
})
Your mutations types project/src/store/mutation-types.js
export const SET_TODOS ='SET_TODOS'
export const PATCH_TODO ='PATCH_TODO'
export const DELETE_TODO ='DELETE_TODO'
export const CREATE_TODO ='CREATE_TODO'
Your module project/src/store/modulse/todos.js
import {
Todos,
} from '#/api/elements'
import {
SET_TODOS, PATCH_TODO, DELETE_TODO, CREATE_TODO
} from '../mutation-types'
// Getters
export default {
state: {
todos: []
},
getters: {
getTodos(state) {
return state.todos
},
},
// Mutations
mutations: {
[SET_TODOS](state, todos) {
state.todos = todos
},
[PATCH_TODO](state, todos) {
let id = todos.id
state.todos.filter(todos => {
return todos.id === id
})[0] = todos
},
[CREATE_TODO](state, todo) {
state.todos = [todo, ...state.todos]
},
[DELETE_TODO](state, {id}) {
state.todos = state.todos.filter(todo =>{
return todo.id !==id
})
},
},
// Actions
actions: {
async setTodos({commit}, queryParams) {
await Todos.list(queryParams)
.then(todos => {
commit(SET_TODOS, todos)
}).catch((error) => {
console.log(error)
})
},
async patchTodo({commit}, todoData) {
await Todos.patch(todoData)
.then(todo => {
commit(PATCH_TODO, todo)
}).catch((error) => {
console.log(error)
})
},
async deleteTodo({commit}, todo_id) {
await Todos.delete(todo_id)
.then(resp => {
commit(DELETE_TODO, todo_id)
}).catch((error) => {
console.log(error)
})
},
async createTodo({commit}, todoData) {
await Todos.create(todoData)
.then(todo => {
commit(CREATE_TODO, todo)
}).catch((error) => {
console.log(error)
})
},
}
In your project/src/main.js
import Vue from 'vue'
import store from './store'
import App from './App.vue'
import Axios from 'axios'
Vue.prototype.$http = Axios;
new Vue({
store,
render: h => h(App),
}).$mount('#app')
In your project/src/App.vue
import {mapActions, mapGetters} from "vuex";
export default {
name: 'App',
components: {},
data() {
return {}
},
methods: {
...mapActions(['setTodos','patchTodo','createTodo','deleteTodo']),
},
computed: {
...mapGetters(['getTodos']),
},
async mounted() {
await this.setTodos()
},
}

TypeError: (0 , _testUtils.createLocalVue) is not a function

This is my code. Can some please help me figure out the error.I am using jest to test out my frontend which I have built using Vue.The line const localVue = createLocalVue(); is giving out the error TypeError: (0 , _testUtils.createLocalVue) is not a function
import { createLocalVue,shallowMount } from '#vue/test-utils'
import Vuex from 'vuex'
import getters from '../../src/store/module/auth/getters.js'
import TheHeader from '#/components/layout/TheHeader.vue'
// const store = new Vuex.Store({
// state: {
// user:null,
// token:'',
// expiresIn:null,
// isUserLoggedIn:false,
// isAdminLoggedIn:false,
// }
// })
describe('TheHeader', () => {
const localVue = createLocalVue();
localVue.use(Vuex);
let store
let state
it('Checks whether the login is correctly displayed', () => {
const cmp = shallowMount(TheHeader, { store,localVue})
expect(cmp.name()).toMatch('TheHeader')
expect(cmp.vm.isLoggedIn()).toBe(false)
})
})
createLocalVue was removed in version 2 of #vue/test-utils, which explains why it's undefined in your example.
To install a Vue plugin (such as Vuex), use the global.plugins mounting option
To mock instance APIs (such as this.$store), use the global.mocks mounting option
import Vuex from 'vuex'
import { shallowMount } from '#vue/test-utils'
import TheHeader from '#/components/TheHeader.vue'
const store = /* Vuex store */
const cmp = shallowMount(TheHeader, {
global: {
plugins: [Vuex],
// OR:
mocks: {
$store: store,
}
}
})
import { mount } from '#vue/test-utils'
import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from '#/views/Home'
creating a fake store
const store = createStore({
state() {
return {
count: 0,
user: {},
}
},
mutations: {
increment(state) {
state.count += 1
},
},
})
Creating the Component
const app = createApp(App)
app.use(store)
let wrapper
beforeEach(() => {
wrapper = mount(App, {
global: {
plugins: [store],
},
computed: { showAlert: () => false },
})
})
now you can do the test
test('Home', async () => {
expect(wrapper.vm.showAlert).toBe(false)
})

How to hide and deny access to some routes in VueJS with Store state?

After authorization, I write the user type to the state, based on this type, I want to show / hide some routes.
src/store/index.js:
import Vue from "vue";
import Vuex from "vuex";
import getters from "./getters";
import user from "./modules/user";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: { user },
getters
});
export default store;
src/store/getters.js:
const getters = {
token: state => state.user.token,
name: state => state.user.name,
type: state => state.user.type
};
export default getters;
src/router/index.js:
import Vue from "vue";
import Router from "vue-router";
import Layout from "#/layout";
Vue.use(Router);
export const constantRoutes = [
{
path: "/login",
component: () => import("#/views/Login"),
hidden: true
},
{
path: "/",
component: Layout,
redirect: "/dashboard",
children: [
{
path: "dashboard",
name: "Dashboard",
component: () => import("#/views/Dashboard"),
meta: { title: "routes.dashboard", icon: "el-icon-odometer" }
}
]
},
{
path: "/providers",
component: Layout,
redirect: "/providers/list",
name: "Providers",
meta: { title: "routes.providers", icon: "el-icon-suitcase-1" },
children: [
{
path: 'list',
name: "List",
component: () => import("#/views/providers/ProvidersList"),
meta: { title: "routes.providersList", icon: "el-icon-document" }
}
]
}
];
const createRouter = () =>
new Router({
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
});
const router = createRouter();
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher;
}
export default router;
Authorization control in a separate file src/permission.js:
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { getToken } from "#/utils/auth";
import getPageTitle from "#/utils/get-page-title";
NProgress.configure({ showSpinner: false });
const whiteList = ["/login"];
router.beforeEach(async (to, from, next) => {
NProgress.start();
document.title = getPageTitle(to.meta.title);
const hasToken = getToken();
if (hasToken) {
if (to.path === "/login") {
next({ path: "/" });
NProgress.done();
} else {
const hasGetUserInfo = store.getters.name;
if (hasGetUserInfo) {
next();
} else {
try {
await store.dispatch("user/getInfo");
next();
} catch (error) {
await store.dispatch("user/resetToken");
Message.error(error || "Has Error");
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
});
router.afterEach(() => {
NProgress.done();
});
As you can see all the code is a collection of copy-paste solutions found somewhere and now I'm completely stuck. How can I hide and deny access to certain routes for users with different state.user.type?
Converting my comment to answer.
Perhaps it will be easier (for you) to use an existing (and tested) solution - something like Vue-ACL or even more advanced.

Change I18n locale don't work for Vee-Validate - VueJS

I am using Vee-Validate plugin for form validation in my VueJS Application. So, my app has more than 1 language, for that, I am using I18n. All the plugins I am using are in separate files under plugins folder and then I am getting all files and registering all plugins in main.js, so in my Vee-Validate.js I have written:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import VeeValidate from 'vee-validate';
import enMessages from "./../locales/validation/en";
import urMessages from "./../locales/validation/ur";
Vue.use(VueI18n);
const i18n = new VueI18n();
i18n.locale = "en";
Vue.use(VeeValidate, {
errorBagName: 'vErrors',
i18nRootKey: 'validations',
i18n,
dictionary: {
en: {
messages: enMessages
},
ur: {
messages: urMessages
}
}
});
But on clicking the change locale button don't change this file locale,
My change locale function:
changeLocale () {
this.$i18n.locale == 'en' ? this.$i18n.locale = 'ur' : this.$i18n.locale = 'en'
this.$vuetify.rtl = this.$i18n.locale == 'ur' ? true : false;
}
Well, I'm not saying your configuration is wrong. I'm going just share mine that is working just fine.
1- vue.config.js
module.exports = {
transpileDependencies: [
'vuetify',
],
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: true,
},
},
};
2- i18n.ts
import Vue from 'vue';
import VueI18n, { LocaleMessages } from 'vue-i18n';
Vue.use(VueI18n);
function loadLocaleMessages(): LocaleMessages {
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i);
const messages: LocaleMessages = {};
locales.keys().forEach((key) => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i);
if (matched && matched.length > 1) {
const locale = matched[1];
messages[locale] = locales(key);
}
});
return messages;
}
export default new VueI18n({
locale: process.env.VUE_APP_I18N_LOCALE || 'en',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: loadLocaleMessages(),
});
3- main.ts
import Vue from 'vue';
import './registerServiceWorker';
import { sync } from 'vuex-router-sync';
import VueLodash from 'vue-lodash';
import Storage from 'vue-ls';
import vuetify from './plugins/vuetify';
import './utils/vee-validate';
// Components
import './components';
// Application imports
import App from './App.vue';
import router from '#/router';
import store from '#/store';
import i18n from './i18n';
// Sync store with router
sync(store, router);
const options = {
name: 'ls', // name variable Vue.[ls] or this.[$ls],
storage: 'local', // storage name session, local, memory
};
Vue.use(Storage, options);
Vue.config.productionTip = false;
Vue.use(VueLodash, { name: 'lodash' });
new Vue({
router,
store,
vuetify,
i18n,
render: h => h(App),
}).$mount('#app');
4- src/plugins/vuetify.ts
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
// import VueI18n from 'vue-i18n';
// import i18n from '#/i18n';
import en from '#/locales/en.json';
import jp from '#/locales/jp.json';
Vue.use(Vuetify);
export default new Vuetify({
lang: {
locales: { en, jp },
current: 'jp',
},
});
5- src/utils/vee-validate.js
/* eslint-disable no-underscore-dangle */
import { extend } from 'vee-validate';
import { required, email, confirmed } from 'vee-validate/dist/rules';
import i18n from '#/i18n';
extend('required', {
...required,
message: (_, values) => i18n.t('GENERAL_VALIDATION_MESSAGES_REQUIRED', values),
});
extend('email', {
...email,
message: (_, values) => i18n.t('LOGIN_FORM_EMAIL_VALID_MESSAGE', values),
});
extend('confirmed', {
...confirmed,
message: (_, values) => i18n.t('CHANGE_PASSWORD_FORM_CONFIRMATION_VALID_MESSAGE', values),
});
6- I use vuex so from my language store
import Vue from 'vue';
import { localize } from 'vee-validate';
import Vuetify from 'vuetify/lib';
import i18n from '#/i18n';
import en from '#/locales/en.json';
import jp from '#/locales/jp.json';
...
const mutations = {
SET_LANG(state, data) {
state.lang = data;
i18n.locale = data;
localize(data, jp);
},
SET_LANG_ERROR() {
window.$messageGlobal('Error switching languages');
},
};
Hope it helps

Vue.js vuex state not working correctly

I'm using Vuex in my project with vue.js 2.0. My app.js looks like this:
import VueRouter from 'vue-router';
import Login from './components/Login.vue';
import Home from './components/Home.vue';
import VModal from 'vue-js-modal';
import Vuex from 'vuex';
import store from './store';
window.Vue = require('vue');
Vue.use(VueRouter);
Vue.use(VModal);
Vue.use(Vuex);
window.Bus = new Vue();
const routes = [
{ path: '/', component: Login, name: 'login' },
{ path: '/home', component: Home, name: 'home', beforeEnter: requireAuth },
];
const router = new VueRouter({
routes // short for `routes: routes`
});
const app = new Vue({
router,
store
}).$mount('#app');
function requireAuth() {
return this.$store.state.isLoggedIn;
}
My store looks like this:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const LOGIN = "LOGIN";
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGOUT = "LOGOUT";
const store = () => {
return new Vuex.Store({
state: {
isLoggedIn: !!localStorage.getItem("token"),
user: null
},
mutations: {
[LOGIN] (state) {
state.pending = true;
},
[LOGIN_SUCCESS] (state) {
state.isLoggedIn = true;
state.pending = false;
},
[LOGOUT](state) {
state.isLoggedIn = false;
}
},
actions: {
login({state, commit, rootState}) {
commit(LOGIN_SUCCESS);
},
setUser({state, commit, rootState}, user) {
//todo
}
}
});
}
export default store;
However when I try to access a value from the state in my requireAuth function:
return this.$store.state.isLoggedIn;
or
return this.store.state.isLoggedIn;
I get the error:
Cannot read property '$store' of undefined
What could be wrong here?
--EDIT--
When I console.log(store); I see:
store() {
var _mutations;
return new __WEBPACK_IMPORTED_MODULE_1_vuex__["a" /* default */].Store({
state: {
isLoggedIn: !!localStorage.getItem("token"),
You have the function declared in the global scope like this:
function requireAuth() {
return this.$store.state.isLoggedIn;
}
So when you call this function this is bound by default to global object. But since ES6 this will be undefined instead of the global object. So you get the error cannot read $store of undefined
Since you are importing the store in app.js you can directly use:
function requireAuth() {
return store.state.isLoggedIn;
}
EDIT
export the created store instance itself, not a function that returns a store instance as follows:
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const LOGIN = "LOGIN";
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGOUT = "LOGOUT";
const store = new Vuex.Store({
state: {
isLoggedIn: !!localStorage.getItem("token"),
user: null
},
mutations: {
[LOGIN] (state) {
state.pending = true;
},
[LOGIN_SUCCESS] (state) {
state.isLoggedIn = true;
state.pending = false;
},
[LOGOUT](state) {
state.isLoggedIn = false;
}
},
actions: {
login({state, commit, rootState}) {
commit(LOGIN_SUCCESS);
},
setUser({state, commit, rootState}, user) {
//todo
}
}
});
export default store;
The requireAuth function should be:
function requireAuth() {
return store.state.isLoggedIn;
}
requireAuth is just a function defined in your app.js and this.$store is how you would refer to the store inside a Vue method. Instead, you can just refer to it in the function as store.

Categories

Resources