Vue Router, refresh shows blank page - vue.js

Im trying to figure out why Vue.js routing, after I refresh my admin page re-directs back to the home component, only showing a blank page, and after a second refresh shows the home component again. I am still logged in as I can still go directly with the url to my admin-page. Meaning the session is still active. Is there a way to force the page to stay on the admin home page when I press F5? I tried things like history mode etc, but cant figure it out.
This is my router.js layout in the root and alos my main router file
import Vue from 'vue'
import Router from 'vue-router'
import firebase from "firebase/app";
import Home from './views/user/Home.vue'
import adminRoute from "./components/routes/admin-routes";
Vue.use(Router);
const router = new Router({
routes: [
{
path: '*',
redirect: '/',
},
{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: false,
}
},
...adminRoute
],
});
router.beforeEach((to, from, next) => {
if (to.matched.some(r => r.meta.requiresAuth === false)) {
next()
} else if (!firebase.auth().currentUser) {
next(false)
} else {
next()
}
});
export default router
and I have my admin-routes.js
import AdminHome from "../../views/admin/AdminHome";
import Users from "../../views/admin/Users";
const adminRoute = [
{
path: '/admin-home',
name: 'AdminHome',
component: AdminHome,
meta: {
requiresAuth: true
},
},
{
path: '/users',
name: 'Users',
component: Users,
meta: {
requiresAuth: true,
}
}
];
export default adminRoute;
I do want to mention that my main page is under views/user/Home.vue and my AdminHome page is views/admin/AdminHome.vue

This problem is return to the server not the built app
you have to manage your 404 not found root
Here you can find the solution
and if you work With Netlify you just create a file in the root of the project ( same place as package.json) name netlify.toml containing
[[redirects]]
from = "/*"
to = "/index.html"
status = 200

in vue4 they did away with the 'next' argument(see here), this is working for me to send people back to the login page, where I'm using firebaseui, I have a simple boolean flag in my vuex store named "isAuthenticated" that I flip on when a user signs on.
NOTE: the following is a boot file for quasar v2 but the logic will
work where ever you have access to the store
import { computed } from 'vue'
export default ({ app, router, store }) => {
console.log('nav.js:')
const isAuthenticated = computed(() => store.state.auth.isAuthenticated)
console.log('isAuthenticated',isAuthenticated.value)
router.beforeEach((to, from) => {
console.log('nav.js:beforeEach:to',to)
console.log('nav.js:beforeEach:from',from)
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!isAuthenticated.value) {
console.log('nav.js:beforeEach:to.redirect')
return '/login'
}
}
})
}

Related

vue router - redirect after successfull authentication

I have a vue app which uses the vue router. I implemented an authentication system for the login routes. How do I get it to redirect automatically to the route the user initially wanted to visit after login was successfull?
This is my code
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "../views/Home.vue";
import Collections from "../views/Collections.vue";
import Login from "../views/Login.vue";
import store from "../store/index";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/login",
name: "Login",
component: Login,
},
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/collections",
name: "Collections",
component: Collections,
//meta: { requiresAuth: true }
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to, from, next) => {
if (!store.getters.isAuthenticated && to.name !== "Login") {
next("/login");
} else {
next();
}
});
export default router;
Instead of just calling next('/login'), you can additionally pass the route that users want to visit as a query parameter, like this:
next({
path: '/login',
query: {
redirect: to.fullPath,
}
})
Then, in the login page, after the successful authentication, you can call
this.$router.replace(this.$route.query.redirect || '/');
It will redirect users to the page they initially want to visit, or to home if there is no information about redirection.
Use cookie storage
this.cookieUrl = this.$route.query.redirecturl
if (this.cookieUrl) {
cookieStorage.setItem('redirecturl', this.cookieUrl, false, 2000000)
}
and after login check cookie
if (cookieStorage.getItem('redirecturl')) {
this.$router.push({
path: cookieStorage.getItem('redirecturl')
})
cookieStorage.removeItem('redirecturl')
The plain and simple approach which could work in that case is simply redirecting back to previous route after successful login.
$router.go(-1)
Your best option is to initially redirect the person to the login page with a parameter that specifies the original page. Something like:
if(!loggedIn) {
// If not authenticated, add a path where to redirect after login.
this.$router.push({ name: 'login', query: { source_path: '/current_route' }});
}
(you can optionally use this.$route.query.page in place of an explicit /current_route string).
Then in the login page have a method that uses the parameter if set, or falls back to the homepage:
this.$router.push(this.$route.query.source_path || '/')

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.

Refreshing page redirects to home using vue router

I am facing a problem with my vuejs project. I am using vue router in a single page application. I can go to any page using vue router. But when I reload the page at any route, it redirects me to / of the project. Here is the code I have written for vue router in router/index.js file.
import Vue from 'vue'
import VueRouter from 'vue-router'
// import store from '../store'
import Home from '../views/Home.vue'
import Login from '#/components/auth/Login.vue'
import Register from '#/components/auth/Register.vue'
import Admin from '#/components/admin/Admin.vue'
import CreateCourse from '#/components/admin/course/CreateCourse.vue'
import Categories from '#/components/admin/Categories.vue'
Vue.use(VueRouter);
function isAuthenticated(to, from, next) {
// if (store.getters['auth/authenticated']) {
// next();
// } else {
// next('/login');
// }
next();
}
function isAdmin(to, from, next) {
// if (store.getters['auth/user'].role === 'super' || store.getters['auth/user'].role === 'admin') {
// next();
// } else {
// next('/');
// }
next();
}
function isNotAuthenticated(to, from, next) {
// if (!store.getters['auth/authenticated']) {
// next();
// } else {
// next('/');
// }
next();
}
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
beforeEnter: isAuthenticated,
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: Login,
beforeEnter: isNotAuthenticated,
},
{
path: '/register',
name: 'Register',
component: Register,
beforeEnter: isNotAuthenticated,
},
{
path: '/admin',
name: 'Admin',
component: Admin,
beforeEnter: isAdmin,
},
];
const router = new VueRouter({
mode: 'history',
routes
});
export default router
What is the problem?
Note: The commented code is to control user access to a specific route. I am calling beforeEnter for each route to check if the user has permission or not. Is there any better solution?
I found what is wrong with my code. Every time I reload the page, I authenticate the user using vuex and if the authentication is successful, I redirect the user to home page. So, every time I refresh the page, I am authenticated and redirected to the home page. Now I have removed the redirect login after login and the problem is solved.

Vue beforeEach() doesn't redirect to the desired page

I'm trying to redirect/continue to a certain page using vue router, After a user signs up with email and password they should be redirected to another page but the home page just gets reloaded.
I'm not implementing login at the moment, Just the signup part. Every example that I follow works fine in redirecting with just "next()"
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Admin from "../views/Admin.vue";
import Overview from "../views/Overview.vue";
import Products from "../views/Products.vue";
import Orders from "../views/Orders.vue";
import { fb } from "../firebase";
Vue.use(VueRouter);
// The 'name' property hasn't been utilized yet
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/admin",
name: "admin",
component: Admin,
// By adding 'requiresAuth' we ensure this route/page and it's children will not be
// accessable by someone who is not authenticated
meta:{ requiresAuth: true },
children:[
{
// Don't put the '/' here
path: "overview",
name: "overview",
component: Overview
},
{
// Don't put the '/' here
path: "products",
name: "products",
component: Products
},
{
// Don't put the '/' here
path: "orders",
name: "orders",
component: Orders
}
]
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
// ============= This is the method in question ==============
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(x => x.meta.requiresAuth);
const currentUser = fb.auth().currentUser;
// This condition always passes, Even after the user is registered, So it always reloads
// the home page
if (requiresAuth && !currentUser) {
next('/');
// This never runs
} else {
next();
}
});
export default router;

Occurs dead loop in router.beforeEach in vue, vue-router

I have issue that i still cant fix it after i try some solution thought google search.
I am using router.beforeEach to check token exist.
If I no login and input localhost/overview in url bar directly,
it need to redirect login page and url redirect to localhost/login but fail and show the error message below,
Maximum call stack size exceeded
How can i modify the router.beforeEach method ?
In router.js
import Vue from 'vue'
import store from '#/store/index'
import Router from 'vue-router'
import Overview from '#/components/Overview'
import Login from '#/components/Login'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Login',
component: Login,
meta: {
requiresAuth: false
}
},
{
path: '/overview',
name: 'Overview',
component: Overview,
meta: {
requiresAuth: true
}
},
{
path: '*',
redirect: '/login',
meta: {
requiresAuth: false
}
}
]
}
router.beforeEach((to, from, next) => {
let token = store.state.token
if (token) {
if (to.query.redirect) {
next({path: to.query.redirect})
} else {
if (['/login'].includes(to.path)) {
next({path: '/overview'})
} else {
next()
}
}
} else {
let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth) {
next({path: '/login', query: { redirect: to.fullPath }})
} else {
next()
}
}
})
export default router
Be sure that your logging path does not require auth itself/that your mechanism to detect if a page needs auth is correct.
Keep in mind that your navigation guard function will be called each time a route is reached, including when you are redirecting the user programatically in your navigation guard itself. So you should take that in account to create a function that will not loop (i.e trigger a redirect that trigger a redirect...).