How to correct, Maximum call stack size exceeded, vue-router? - vue.js

Good day.
I have the following error:
[vue-router] uncaught error during route navigation:
vue-router.esm.js:1897 RangeError: Maximum call stack size exceeded
at String.replace (<anonymous>)
at resolvePath (vue-router.esm.js:597)
at normalizeLocation (vue-router.esm.js:1297)
at Object.match (vue-router.esm.js:1341)
at VueRouter.match (vue-router.esm.js:2461)
at HashHistory.transitionTo (vue-router.esm.js:1865)
at HashHistory.push (vue-router.esm.js:2267)
at eval (vue-router.esm.js:1952)
at router.beforeEach (index.js:116)
at iterator (vue-router.esm.js:1935)
According to the error it is in my file of routes, which I have it in the following way:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/Home'
import Vehiculos from '../components/Vehiculos'
import Perfil from '../components/Perfil'
import Login from '../components/Login'
import TutorialIntroduccion from '../components/TutorialIntroduccion'
import Politicas from '../components/Politicas'
import Parqueo from '../components/Parqueo'
import Politicas from '../components/Politicas'
import Historial from '../components/Historial'
import firebase from 'firebase'
Vue.use(Router)
let tutorialVisto = localStorage.getItem("Tutorial");
const router = new Router({
routes: [
{
path: '*',
redirect: '/login'
},
{
path: '/',
redirect: '/tutorial'
},
{
path: '/tutorial',
name: 'tutorial',
component: TutorialIntroduccion,
meta: {
tutorialVisto: tutorialVisto,
autentificado: false
},
beforeEnter: (to, from, next) => {
let tutorialVisto = to.matched.some(record=>record.meta.tutorialVisto);
if (tutorialVisto)next('login');
else next();
}
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/home',
name: 'home',
component: Home,
meta: {
autentificado: true
}
},
{
path: '/parqueo/:id',
name: 'parqueo',
component: Parqueo,
meta: {
autentificado: true
}
},
{
path: '/vehiculos',
name: 'vehiculos',
component: Vehiculos,
meta: {
autentificado: true
}
},
{
path: '/perfil',
name: 'perfil',
component: Perfil,
meta: {
autentificado: true
}
},
{
path: '/politicas',
name: 'politicas',
component: Politicas,
meta: {
autentificado: true
},
},
{
path: '/historial',
name: 'historial',
component: Historial,
meta:{
autentificado: true
}
}
]
})
router.beforeEach((to, from, next) => {
let usuario = firebase.auth().currentUser; //Debe ser otra Promesa si esta autenticado o no.
let autorizacion = to.matched.some(record=>record.meta.autentificado);
let tutorialVisto = to.matched.some(record=>record.meta.tutorialVisto);
if (autorizacion && !usuario) {
next('login');
}
else if (!autorizacion && usuario) {
next('home');
}
else{
next();
}
})
export default router;
The problem arises when I am in the parking lot view and then when I log in, it does not redirect me to the vita login, but it gives me that error and stays in the same view, although it does close the firebase session. If I am in any of the other views, for example, vehicles, profile or main and then I give in closing session does not generate me error.
The session closing code is the following:
linkto(pathname) {
this.$router.push({ path: pathname })
if(pathname=="/login") {
firebase.auth().signOut().then(() => this.$router.replace('login'))
}
},

According to vue router's docs:
{
// will match everything
path: '*'
}
It is usually used to redirect to a 404 page not another route. In your case, you are calling a new route /login and it matches in * as well, which causes the loop and the Maximum call stack size exceeded.

You have multiple spelling mistakes in your next handlers. These calls accept the name of a route, and if you pass it a name of an route that does not exists, it will behave unspecified.
From what I can see is that you are trying to redirect to login, while you actually called the route Login

It happened to me too.
So after my investigation I have found if you are using Vuejs v. 2.* you have to use the vue-router of v. 2.* (not version 3).
Please see the following examaple:
package.json:
"dependencies": {
"vue": "^2.6.11",
"vue-router": "^2.8.1"
router.ts:
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import { Component } from "vue-router/types/router";
import Home from "#/views/Home.vue";
import NotFound from "#/views/NotFound.vue";
import MyPage from "#/views/MyPage.vue";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/",
name: "Home",
component: Home as Component
},
{
path: "/my-page",
name: "MyPage",
component: MyPage as Component
},
{
// will match everything else
path: '*',
name: "NotFound",
component: NotFound as Component
}
];
const router = new VueRouter({
mode: "history",
routes
});
export default router;

Related

Vue router - navigation guard is skipped when using router.push()

I have a Vue SPA with i18n and some views that require authentication via navigation guard.
When i am not authenticated and go to url via my browser:
examplepage.com/en/lockedpage
i get redirected to:
examplepage.com/en/login
which is good, however when i click a button that runs:
#click="$router.push(`/${$i18n.locale}/lockedpage`)"
i get in to the page even if i am not authenticated.
I want to get redirected to the login page if not authenticated
this is my router.js:
import Vue from 'vue';
import Router from 'vue-router';
import Home2 from './views/Home2.vue';
import Login from './views/Login.vue';
import Register from './views/Register.vue';
import ErrorLanding from './views/ErrorLanding.vue'
import Root from "./Root"
import i18n, { loadLocaleMessagesAsync } from "#/i18n"
import {
setDocumentLang
} from "#/util/i18n/document"
Vue.use(Router);
const { locale } = i18n
export const router = new Router({
mode: 'history',
base: '/',
routes: [
{
path: '/',
redirect: locale
},
{
path: "/:locale",
component: Root,
children: [
{
name: 'Home',
path: '',
component: Home2,
},
{
name: 'Home2',
path: '/',
component: Home2,
},
{
name: 'Login',
path: 'login',
component: Login,
},
{
path: 'register',
component: Register,
},
{
path: 'lockedpage',
name: 'lockedpage',
webpackChunkName: "lockedpage",
meta: {authRequired: true},
component: () => import('./views/LockedPage.vue')
},
{
path: '*',
component: ErrorLanding,
name: 'NotFound'
}
]
}
],
router.beforeEach((to, from, next) => {
if (to.params.locale === from.params.locale) {
next()
return
}
const { locale } = to.params
loadLocaleMessagesAsync(locale).then(() => {
setDocumentLang(locale)
const publicPages = [ `/`, `/${locale}`, `/${locale}/`];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
const redirect = to.path;
if (authRequired && loggedIn === null) {
if(to.meta.authRequired === false) {
next();
}
else
next({ name: 'Login', query: { redirect: redirect } });
} else {
next();
}
})
next()
});
Why does my navigationguard skip when using router.push() ?
This issue started after adding i18n, with localeredirect. so all routes comes after a locale for example: /en/.../
As Estus points out in the comments, the issue is that the first thing you're checking for is if the locales match, and if they do you're calling next() and sending the user to the page.
As outlined here:
Make sure that the next function is called exactly once in any given pass through the navigation guard. It can appear more than once, but only if the logical paths have no overlap, otherwise the hook will never be resolved or produce errors.
If you need to keep the locale check between the to and from pages, you could do something like:
if (to.params.locale === from.params.locale && loggedIn) {
next()
return
}
which will check if the loggedIn variable is truthy before pushing the user to the page they're trying to navigate to.
I believe just removing the if statement that checks if the locales match would also work.

Navigating to route returns Maximum call stack size exceeded

I want to navigate the user to /home once he clicks on a box, but currently the redirection does not work and I get this error:
Maximum call stack size exceeded
What is causing this error and how can I fix it?
here is my relevant html:
<router-link to="/home"> <md-button class="view-captable-btn" v-for="item in capTables" :key="item.contractAddress" v-model="capTables" #click="getCapTableId(item.contractAddress, item); getCaptableName(item.label, item)" >
<p>{{item.label}}</p>
<p class="contract-address-p"> {{item.contractAddress}}</p>
</md-button>
</router-link>
my method:
getCapTableId(contractAddress, item) {
let address = item.contractAddress
store.commit('saveCapTableAddress', address)
},
and my protected route logic :
import Vue from 'vue'
import Router from 'vue-router'
import firebase from "firebase/app"
import "firebase/auth"
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/unauthorized',
name: 'Unauthorized',
component: Unauthorized
},
{
path: '/activity-log',
component: ActivityLog,
name: 'ActivityLog'
},
{
path: '/captables',
name: 'CapTables',
component: CapTables,
meta: {
requiresAuth: true
},
},
{
path: '*',
component: NotFound,
name: 'NotFound',
},
],
mode: 'history'
})
router.beforeEach((to, from, next) => {
const currentUser = firebase.auth().currentUser
const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if(requiresAuth && !currentUser) next('/unauthorized')
else if (!requiresAuth && currentUser) next('home')
else next()
});
export default router
I tried using pushing the route with this.$route.push('/home') still doesn' work.

Not redirecting to Login page with router.beforeEach VUEJS

I need help, I've been trying to debug this for hours this is my the whole code for my routing:
I need this to automatically redirect to the login page and it won't redirect with using the router.beforeEach and there is no error on the console.
import Vue from "vue";
import Router from "vue-router";
import store from "../store.js";
import Login from "#/views/Login.vue";
import Home from "#/views/Home.vue"
Vue.use(Router);
let router = new Router({
mode: "hash",
linkActiveClass: "open active",
scrollBehavior: () => ({ y: 0 }),
routes: [
{
path: "/home",
name: "Home",
component: Home,
meta: {
requiresAuth: true
},
children: [
]
}, {
path: "/login",
name: "login",
component: Login
},
]
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
console.log(store.getters.isLoggedIn);
if (store.getters.isLoggedIn) {
next();
return;
}
next("/login");
} else {
next();
}
});
export default router;
Any help would do.

Redirect to specific url in case of wrong url in vuejs

I have two separate routing files where I am importing the component and defining their routing in each of its file and using it in index.js file. Here are my files code:
//router1.js
import Layout1 from 'Layouts/Panel.vue';
const Users = () => import('Views/Users.vue');
const Reports = () => import('Views/Reports.vue');
export default {
path: '/layout1',
component: Layout1,
redirect:'/layout1/reports',
children:[
{
path: 'reports',
component: Reports,
name:'Reports'
},
{
path: 'users',
component: Users,
name:'Users'
}
]
}
//router2.js
import Layout2 from 'Layout/Panel2';
const Demo1 = () => import('Views/Demo1');
const Demo2 = () => import('Views/Demo2');
export default {
path: '/',
component: Layout2,
redirect:'/demo1',
children:[
{
path: '/demo1',
component: Demo1
},
{
path: '/demo2',
component: Demo2
}
]
}
// index.js
import Vue from 'vue'
import Router from 'vue-router'
import router1 from './router1';
import router2 from './router2';
const NotFound = () => import('Views/NotFound.vue');
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
router1,
router2,
{
path: '*',
component: NotFound,
name:'NotFound',
},
]
})
Now, I want to redirect to specific url i.e "not-found" in case of wrong URL. In "NotFound" component I am adding below line of code in mounted lifecycle hook which redirects to URL "not-found".
this.$router.replace({ path: 'not-found' });
But if URL is having parameters or query string it will append to it. For e.g- http://localhost:8080/home/not-found
What I want is that it only shows http://localhost:8080/not-found How should I achieve this. Please help. Thanks!
try this in your mounted function. worked on my side.
this.$router.push({path: '/not-found'})

Vue.js router only loading component from navigation and not from URL

how to solve this error in vuejs-
index.js?3672:101 Uncaught TypeError: Cannot read property 'beforeEach' of undefined
import VueRouter from 'vue-router';
Vue.use(VueRouter);
Vue.use(Router);
export default new Router({
// history:true,
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/Dashboard/dashboard',
name: 'Business Intelligence Platform',
beforeEnter: requireAuth,
component: dashboard
},
export function requireAuth(to, from, next) {
if (!formSubmit()) {
next({
path: '/',
query: { redirect: to.fullPath }
});
} else {
next();
}
}