Access vuex store in before Vue instance is initialized - javascript

I'd like to check if the user is validated before entering routes. I'm using vue-router's beforeEach to tackle this. But I realize that I can check the vuex store before the vue instance is initialized.
Main.js
import Vue from "vue";
import Vuetify from 'vuetify';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import VeeValidate from 'vee-validate';
import store from '../store/store.js';
import App from '../app.vue';
import axios from 'axios';
import progressBar from '../plugins/progress-bar';
import { routes } from '../router-config';
import { sync } from 'vuex-router-sync';
import 'vuetify/dist/vuetify.min.css'
Vue.use(VeeValidate)
Vue.use(VueRouter)
Vue.use(Vuetify)
Vue.use(Vuex)
Vue.config.productionTip = false
axios.defaults.headers.common['Accept'] = 'application/json'
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(document.createElement('app'))
const router = new VueRouter({
routes,
mode: 'hash',
saveScrollPosition: true,
});
sync(store, router)
router.beforeEach((to, from, next) => {
debugger;
if (to.meta.requiresAuth && store.getters.isLoggedIn) {
next({ path: '/' })
} else if (to.path === "/") {
next({ path: '/dashboard'})
} else {
next()
}
});
const app = new Vue({
el: 'app',
router,
store,
axios,
render: h => h(App),
template: '<App/>',
components: {
App,
}
});
})
How can I access this so that I can do something like this this.$store.getters.isLoggedIn? Am I thinking of this the right way?

You don't need this.$store. You have store. Just use store.
store.getters.isLoggedIn
this.$store is just a reference to store that you can use inside Vue components. But anywhere you import the store you have access to everything you need.

Related

Migrating Vue 2 to Vue 3, typeError: Vue is not a constructor

How can I migrate my Vue 2 syntax to Vue 3, because I'm receiving the following error:
TypeError: Vue is not a constructor.
Right now I'm using Vue 3:
let app;
firebase.auth().onAuthStateChanged(user => {
console.log("user", user);
if (!app) {
app = new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
}
});
To
import { createApp } from "vue";
const app = createApp({
});
app.mount("#app");
The equivalent of your code in Vue 3, Vuex 4, Vue Router 4 would be something like:
import { createApp } from 'vue'
import store from './store'
import router from './router'
import App from './App.vue'
let app;
firebase.auth().onAuthStateChanged(user => {
console.log("user", user);
app = createApp(App);
app.use(store);
app.use(router);
app.mount("#app");
});
The store syntax is slightly different in store.js:
import { createStore } from 'vuex'
// now uses `createStore`
export default createStore({
state: {},
getters: {},
mutations: {},
actions: {}
})
And the router in router.js:
import { createWebHistory, createRouter } from "vue-router";
import Home from "#/views/Home.vue";
import About from "#/views/About.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
component: About,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;

Watch changes in $route object - Vue Router

I'm doing a project of small CRM. In the login form, I have a component that shows an alert message when email or password is incorrect. When someone is trying to login incorrectly, then type the correct info and then logout, the message still appears unless the page is refreshed.
I tried to solve that within watch by accessing $route, so every time the route is changed, I clear the state of the message.
Alert.vue:
<template>
<div :class="'alert ' + alert.type">{{alert.message}}</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: mapState({
alert: state => state.alert
}),
methods: mapActions({
clearAlert: 'alert/clear'
}),
watch: {
$route (to, from){
console.log('inside $rout');
this.clearAlert();
}
}
};
</script>
main.js:
import Vue from 'vue';
import { store } from './_store';
import { router } from './_helpers';
import App from './components/App';
import './css/main.css';
new Vue({
el: '#app',
router,
store,
render: h => h(App)
});
router.js:
import Vue from 'vue';
import Router from 'vue-router';
import Dashboard from '../components/Dashboard.vue';
import LoginPage from '../components/LoginPage.vue';
import UserPage from '../components/UserPage.vue';
Vue.use(Router);
export const router = new Router({
mode: 'history',
routes: [
{ path: '/app', component: Dashboard },
{ path: '/login', component: LoginPage },
{ path: '/app/user-info', component: UserPage },
{ path: '*', redirect: '/app' }
]
});
router.beforeEach((to, from, next) => {
const allowedPages = ['/login'];
const authRequired = !allowedPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
if (authRequired && !loggedIn) {
return next('/login');
}
next();
})
I tried to do both methods in documentation https://router.vuejs.org/guide/essentials/dynamic-matching.html
For some reason, the $route isn't recognized & I can't access it.
I should also mention that in my main.js I import the router.js file which imports Router from 'vue-router' & instantiates it, so $route should be accessible from all components.
can someone shed some light on why?
link to my project: repo
The $route watcher setup you have is correct, and your component has access to $route, as can be seen if you log it in mounted().
The problem is that the watcher is in Alert.vue, which is a component that is on a page being navigated away from, so it gets destroyed, preventing the watcher being invoked. If you move the $route watcher to a component that is always kept alive (e.g., App.vue), you'll see that it works correctly.

Vue Routing Guard TypeError

I am trying to guard home page and route user to login page if he/she is not signed in.
To do that I made I made router object so that I can use beforeEach() function.
But I get this error:
This error occurs after I try to make a constant object of router.
router.js is:
import Vue from 'vue';
import Router from 'vue-router';
import firebase from 'firebase';
import Home from './views/Home.vue';
import Signup from './components/auth/Signup.vue';
import Login from './components/auth/Login';
Vue.use(Router);
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: true,
},
},
{
path: '/signup',
name: 'Signup',
component: Signup,
},
{
path: '/login',
name: 'Login',
component: Login,
},
],
});
// router guards
router.beforeEach((to, from, next) => {
// check to see if routh require auth
if (to.matched.some(rec => rec.meta.requiresAuth)) {
// check state of user
const user = firebase.auth().currentUser;
if (user) {
next();
} else {
next({ name: 'Login' });
}
} else {
next();
}
});
This is is in main.js file.
import Vue from 'vue';
import firebase from 'firebase';
import router from './router';
import App from './App.vue';
Vue.config.productionTip = false;
const app = null;
// Wait for firebase init the user
firebase.auth().onAuthStateChanged(() => {
// init the app if not created
if (!app) {
new Vue({
router,
render: h => h(App),
}).$mount('#app');
}
});
Add the below changes
Add this line to last in router.js
export default router;
Add In main.js
import router from './router'; (path should point to your router.js)
new Vue({
router,
....
....
})

Attaching vue-gtm (google tag manager) to a Router instance

Using this package: https://www.npmjs.com/package/vue-gtm
In router.js (vue cli 3) i'm trying to attach it to a router instance:
import Vue from 'vue'
import Router from 'vue-router'
import VueGtm from 'vue-gtm'
Vue.use(VueGtm, {
id: 'GTM-xxxxxxx',
enabled: true,
debug: true,
vueRouter: Router
})
export default new Router({
mode: 'history'
})
But, obviously, this won't work. How can i attach vue-gtm to a Router in my case, where i export Router instance, not setting it to a variable:
const router = new Router({})
You're incorrectly passing the Router class for vueRouter in:
Vue.use(VueGtm, {
//vueRouter: Router, // <-- DON'T DO THIS
})
The vueRouter value should be the router instance, so router.js should look similar to this:
const routes = [
//...
]
const router = new Router({
mode: 'history',
routes
})
Vue.use(VueGtm, {
vueRouter: router, // <-- router instance
//...
})
export default router

must call Vue.use(Vuex) before creating a store instance

I cant't figure out why I am getting this error. Everything looks properly.
Import store to the component like this.
import store from './store';
new Vue({
components: {
SomeComponent
},
store
});
My store looks like this
import Vue from 'vue';
import Vuex from 'vuex';
import * as getters from './getters';
import * as actions from './actions';
import mutations from './mutations';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
something
}
})
Please any help.
Thanks
Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance.
Using Vue CLI and setting up like this works for me
in store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
something: ['something']
}
})
in main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
I've had a similar problem, and turns out that my modules were returning a Vuex.Store instance instead of a javascript object.
My files was like:
app.js
import Vue from 'vue'
...
import store from './store'
...
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import myModule from './my-module'
...
export default new Vuex.Store({
modules: { myModule }
....
})
my-module/index.js (Here was my problem)
import Vuex from 'vuex'
...
export default new Vuex.Store({
namespaced: true,
state: { ... },
...
})
My mistake was that I must have only one store, the root store, the others are modules of root. So I must not instantiate a new store, but return a config object instead. Like so:
my-module/index.js (Corrected version)
...
export default {
namespaced: true,
state: { ... },
...
}
So, if anyone arrived here with the same problem, I hope it can save you some time.
See https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart for how they do it in their sample app.
app.js
import 'babel-polyfill'
import Vue from 'vue'
import App from './components/App.vue'
import store from './store'
import { currency } from './currency'
Vue.filter('currency', currency)
new Vue({
el: '#app',
store,
render: h => h(App)
})
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import cart from './modules/cart'
import products from './modules/products'
import createLogger from '../../../src/plugins/logger'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
actions,
getters,
modules: {
cart,
products
},
strict: debug,
plugins: debug ? [createLogger()] : []
})
#katieh
Ou.. I'e resolved this problem. I had 'vue' instead of 'vue-loader' in webpack. So, *** happens then i remove vue-loader work well
you literally need to add something to the store; a state, module or a getter
I create a repositorie: vue-use-vuex to solved this bug.
You can Use it to fixed:
npm install vue-use-vuex --save
add one line code in you entry:
import 'vue-use-vuex'
The error will not be seen.

Categories

Resources