How do I get current route in onMounted on page refresh? - javascript

When reloading page, I want to get current route. Sadly route.name is undefined, router.currentRoute is RefImpl object, which has correct route with '/team' inside. router.currentRoute.value is just root '/', not '/team', as expected. Is it possible to get correct value from RefImpl?
import { useRouter, useRoute } from 'vue-router'
export default {
name: 'Canvas',
components: { Ring2, Map },
setup() {
const router = useRouter()
const route = useRoute()
onMounted(() => {
console.log(route.name) //undefined
console.log(router.currentRoute) //RefImpl with correct value ('/team')
console.log(router.currentRoute.value) // route is '/'
const rawObject = {...router.currentRoute}
console.log(rawObject) // value is '/'
...
Router is set up like this:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/team',
name: 'Team',
component: () => import('../views/Team.vue')
},
...
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router

This happens because the router hasn't yet completely resolved the initial navigation when you refresh the page, so route refers to the default (/) initially in onMounted.
Vue Router's isReady() returns a Promise that resolves when the router has completed the initial navigation, so your onMounted hook can await that Promise before trying to read route.path:
import { useRoute, useRouter } from 'vue-router'
import { onMounted } from 'vue'
export default {
setup() {
const route = useRoute()
const router = useRouter()
onMounted(async () => {
await router.isReady() 👈
console.log('route.path', route.path)
})
},
}
demo

Try using the composable function useRoute :
import {
useRoute
} from 'vue-router'
import {
computed
} from 'vue'
setup() {
const route = useRoute();
const path = computed(() => route.path)
}

Related

Why is router.push not working? [Vue3] [Vuex4]

I have some issues with Vue 3 and Vuex.
I'm trying to redirect users when logged in in my Vuex file, but it's not working as expected.
It's not returning any errors, it's changing a link, but not redirected to another page.
My action looks like this;
actions: {
async login(commit: any, payload: any ) {
const cookie_token = useCookies();
API.post('/login', {
email: payload.email.value,
password: payload.password.value
})
.then((response: any) => {
notif.success('Welcome back, ' + response.data.player.name)
cookie.set('user', response.data)
commit.commit('loginSuccess', response.data)
router.push({
name: 'index',
})
}).catch((e) => (
console.log(e.message)
)
)
}
},
And the router is getting files where routes are defined.
And here is my full router file:
import {
createRouter as createClientRouter,
createWebHistory,
} from 'vue-router'
import * as NProgress from 'nprogress'
// import routes from 'pages-generated'
import type { RouteRecordRaw } from "vue-router";
// Then we can define our routes
const routes: RouteRecordRaw[] = [
// This is a simple route
{
component: () => import("/#src/pages/index.vue"),
name: "index",
path: "/",
props: true,
},
{
component: () => import("/#src/pages/auth.vue"),
path: "/auth",
props: true,
children: [
{
component: () => import("/#src/pages/auth/login.vue"),
name: "auth-login",
path: "login-1",
props: true,
},
{
component: () => import("/#src/pages/auth/login.vue"),
name: "auth-signup",
path: "singup",
props: true,
},
],
},
{
component: () => import("/#src/pages/[...all].vue"),
name: "404",
path: "/:all(.*)",
props: true,
},
];
export function createRouter() {
const router = createClientRouter({
history: createWebHistory(),
routes,
})
/**
* Handle NProgress display on-page changes
*/
router.beforeEach(() => {
NProgress.start()
})
router.afterEach(() => {
NProgress.done()
})
return router
}
export default createRouter()
Have in mind that it's working on other files, and I can see that router is triggered here, but not chaning a page, only on vuex is not working. If it's not working, why there is no error?
You're creating more than one instance of Vue Router. You should export the same router instance, not a function creating a new instance each time it gets called.
The following code will likely yield the desired outcome:
import {
createRouter,
createWebHistory,
} from 'vue-router'
import * as NProgress from 'nprogress'
import type { RouteRecordRaw } from "vue-router";
const routes: RouteRecordRaw[] = [
// your routes here...
];
let router;
export function useRouter() {
if (!router) {
router = createRouter({
history: createWebHistory(),
routes,
})
router.beforeEach(() => {
NProgress.start()
})
router.afterEach(() => {
NProgress.done()
})
}
return router
}
I'm placing the router instance in the outer scope, so you always get the same instance when calling useRouter().
Consume it using:
import { useRouter } from '../path/to/router'
const router = useRouter();

I want to redirect to the login screen when I try to access the screen after login when I am not logged in

↓Error Message
Uncaught (in promise) Error: Infinite redirect in navigation guard at eval
↓main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store/store'
import firebase from 'firebase';
import config from './firebase.config';
firebase.initializeApp(config);
const app = createApp(App); app.use(router); app.use(store); app.mount('#app');
router.beforeEach((to, from, next) => {
if (to.path === '/home') {
firebase.auth().onAuthStateChanged(user => {
if (user) {
next('/home')
} else {
next('/')
}
})
} else {
next();
} });
↓router.js
import { createRouter, createWebHistory } from 'vue-router';
import Login from './components/Login';
import SignUp from './components/SignUp';
import Home from './components/Home';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Login }, //Login screen path
{ path: '/signup', component: SignUp }, //New registration screen path
{ path: '/home', component: Home }, //Screen path after login
],
});
export default router;
As mentioned above, I tried to write my own code, but it doesn't work very well.
Is it better to prepare a separate flag instead of checking the user information with onAuthStateChanged?
I would appreciate it if you could teach me 🙇‍♂️
Changing next('/home') to next()
Reason: If you use next('/home'), below code would be run again and make a infinite loop
router.beforeEach((to, from, next) => {
if (to.path === '/home') {
// this would be running again
...
}

Vue-router redirecting not working on store.js dispatch function

I'am trying to use vue-router in my store.js file methods to redirect a user after performing a log in but for whatever reason it just send him back to the previous page. If i use vue-router in any of my .vue pages it works just fine.
What am i doing wrong?
here is my routes.js file
import Vue from 'vue'
import VueRouter from 'vue-router'
import login from '#/views/login'
import page2 from '#/views/page2 '
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{
path: '/',
name: 'login',
component: login
},
{
path: '/page2 ',
name: 'page2 ',
component: page2
}
]
})
Here is my store.js file
import Vue from 'vue'
import Vuex from 'vuex'
import axios from '#/axios.js'
import router from '#/routes';
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
token: ''
},
mutations: {
login (state, payload){
return state.token = payload;
}
},
actions: {
login ({ commit }, payload) {
axios.get('/login',{
auth: {
username: payload.username,
password: payload.password
}
}).then(function (response) {
commit('login', response.data['user-token'])
router.go('page2')
})
}
}
})
export default store;
router.go(n) is used to navigate in the history stack: https://router.vuejs.org/guide/essentials/navigation.html#router-go-n
Use router.push({name: "page2"}) instead.

Router not working when moving code into helper file

I tried to create some organization in my Vue app, so I moved my router confirguration to a separate file:
# /_helpers/router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import MemberDetail from '../MemberDetail';
import LoginPage from '../LoginPage';
Vue.use(VueRouter)
const routes = [
{ path: '/', component: MemberDetail },
{ path: '/login', component: LoginPage },
];
export const router = new VueRouter({routes});
router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
if (authRequired && !loggedIn) {
return next('/login');
}
next();
})
Then I add the exported router in my main application.js:
import Vue from 'vue/dist/vue.esm'
import App from '../components/app.vue'
import { router } from '../components/_helpers';
document.addEventListener('DOMContentLoaded', () => {
new Vue({
el: '#app',
router,
render: h => h(App)
});
})
In my App.vue, I try to display the router-view:
<template>
<div class="page-container">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
};
</script>
<style scoped>
</style>
Unfortunataly this results in the following error:
[Vue warn]: Unknown custom element: <router-view> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I don't understand what's wrong... I'm adding the router to the new Vue call, so I think it should be available.
Thanks

Access Vuex mutators in navigation guards

I'm building an app with Laravel + VueJS. In order to restrict some routes, I use navigation guards. The problem is that I need to access Vuex mutators in order to know if the current user is logged in. The thing is that store is defined, but I cannot use the mutator from the router. I got this error: TypeError: Cannot read property 'commit' of undefined but as I said, store is well defined. Does someone have an idea ? Thanks !
routes
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '#/components/Hello'
import Register from '#/components/Register'
import Login from '#/components/Login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello,
meta: {
showNavigation: true,
requireAuthentication: true
}
},
{
path: '/register',
component: Register,
meta: {
showNavigation: false,
requireAuthentication: false
}
},
{
path: '/login',
component: Login,
meta: {
showNavigation: false,
requireAuthentication: false
}
}
],
mode: 'history'
})
store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
access_token: null,
expires_in: 0
},
mutations: {
setToken (state, response) {
state.access_token = response.body.access_token
state.expires_in = response.body.expires_in + Date.now()
},
getToken (state) {
if (!state.access_token || !state.expires_in) return null
if (state.expires_in < Date.now()) this.commit('destroyToken')
return state.access_token
},
destroyToken (state) {
state.access_token = null
state.expires_in = 0
},
isAuthenticated (state) {
return this.commit('getToken') !== null
}
},
actions: {
getOauthToken (context, user) {
var data = {
client_id: 2,
client_secret: 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
grant_type: 'password',
username: user.email,
password: user.password
}
Vue.http.post('oauth/token', data)
.then(response => {
context.commit('setToken', response)
})
}
}
})
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import { store } from './store'
import VueResource from 'vue-resource'
import VeeValidate from 'vee-validate'
Vue.config.productionTip = false
Vue.use(VueResource)
Vue.use(VeeValidate)
Vue.http.options.root = 'http://codex.app'
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requireAuthentication)) {
console.log(store)
console.log(store.commit('isAuthenticated'))
if (!store.commit('isAuthenticated')) {
next('/login')
} else {
next()
}
} else {
next()
}
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
when we commit mutations, it refers to change the state and ONLY the state.when you need more complex mutations to change the state, using actions instead.

Categories