Using Vue 2, I want to run a check before any page elements are rendered, to determine whether the user is signed in and if so, redirect them to another page.
Looking at the Vue Lifecycle, it's my understanding that beforeMount is first in this cycle. However, the page still appears for half a second before redirecting (in my case, to Dashboard)
beforeMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.$router.push({ name: 'Dashboard'})
}
});
}
I've tried other Lifecycle options and none of the others work either. What am I doing wrong?
Looking at the Vue's lifecycle diagram:
beforeCreate and created hooks are earlier than beforeMount. You should use either one of them.
You have to use Guard for this. you have to check auth before going to route on router.js file. you can use beforeEnter into your route path.
read more about that here: https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard
Related
I have a Vue app which does a little localStorage and server check on app load, to determine where to initially route the user.
This is in the App's main entry component, in the created() hook
My problem is that the default / route's Component visibly loads first, then the server call and everything happens which causes the user the route to their correct location
How can I delay the rendering of the initial component until my app's main component created() method completes, and then purposely navigates the user to the correct route?
I had this problem before and I firmly believe that you must have the initial files for your routes and your router configuration.
In the configuration, you could handle the permission and router before each route and with next() . In the router file, you can set your params and check them in the index.js file(router configuration)
you could also use your localStorage data in Router.beforeeach
EDIT: I just saw you used the created method... like mentioned below use beforeRouteEnter instead with the next() parameter it provides
First of all I wouldn't recommend using a delay but instead a variable that keeps track if the API call is done or not. You can achieve this using the mounted method:
data() {
return {
loaded: false,
}
}
async mounted() {
await yourAPICALL()
if (checkIfTokenIsOkay) {
return this.loaded = true;
}
// do something here when token is false
}
Now in your html only show it when loaded it true:
<div v-if="loaded">
// html
</div>
An better approuch is using the beforeRouteEnter method which allows you to not even load the page instead of not showing it: https://router.vuejs.org/guide/advanced/navigation-guards.html
I got a Nuxt application, and in some special route, I want to prevent user from leaving the page by showing plain confirm javascript dialog.
I did some beforeRouteLeave <- this kinda thingy introduced in the Vue official documentation, but none of them seemed work in Nuxt.
And Nuxt recommends users to use middleware for doing this 'beforeRoute' things. Here's my code.
export default function (context) {
if (process.client &&
context.from.path.includes("board/write") &&
context.route.name !== "board-articleId") {
if (!confirm("Are you sure you want to leave the page?")) {
context.next(false)
}
}
}
As you can see, I'm checking if my current route is certain page (context.from.path...), ask user if user wants to leave the page. And if they canceled, which makes confirm as false, do
next(false)
and it works fine as it makes the user stay on the page.
But the problem is, the loading bar of the browser still loads even if the page doesn't change. And it looks like the route is still changing anyway despite the actual page doesn't change.
How can I prevent this to happen?
To make sure the address bar query (?bla=bla) not touched I recommend doing this:
export default function ({ from }) {
redirect(from);
}
I could have used
redirect(from.path)
instead of
next(false)
For the sake of information,
the incoming argument 'context' has some properties like below:
from, route, next, redirect...
Without reloading the whole page I need to reload the current route again (Only a component reload) in a vue app.
I am having a path in vue router like below,
{
path: "/dashboard",
name: "dashboard",
component: loadView("Dashboard"),
},
When user clicks on the Dashboard navigation item user will be redirected to the Dashboard page with vue router programmatic navigation
this.$router.push({ name: "dashboard" });
But when user already in the dashboard route and user clicks the Dashboard nav item again nothing happens. I think this is vue router's default behaviour. But I need to force reload the Dashboard component (Not to refresh the whole page).
I can't use beforeRouteUpdate since the router is not updated. Also I have tried the global before guards like beforeEach. But it is also not working.
How can I force reload the dashboard component without reloading the whole page?
It can be done in two ways.
1) Try doing vm.$forceUpdate(); as suggested here.
2) You can take the strategy of assigning keys to children, but whenever you want to re-render a component, you just update the key.
<template>
<component-to-re-render :key="componentKey" />
</template>
<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>
Every time that forceRerender is called, the prop componentKey will change. When this happens, Vue will know that it has to destroy the component and create a new one.
What you get is a child component that will re-initialize itself and “reset” its state.
Not mentioned here, but as the offered solutions require a lot of additional work just to get the app to render correctly, which imo is a brittle solution.. we have just implemented another solution which works quite well..
Although it is a total hack.
if (this.$route.name === redirect.name) {
// this is a filthy hack - the vue router will not reload the current page and then have vue update the view.
// This hack routes to a generic page, then after this has happened the real redirect can happen
// It happens on most devices too fast to be noticed by the human eye, and in addition does not do a window
// redirect which breaks the mobile apps.
await this.$router.push({
name: RouteNames.ROUTE_REDIRECT_PLACEHOLDER
});
}
... now continue to do your normal redirect.
Essentially, redirect to a placeholder, await the response but then immediately continue to another page you actually wanted to move toward
I have a project it's routing strucher is like this.
1. /
2. admin-panel/:type
2.1 create-user
2.2 update-user
2.3 etc...
3. forgot password
My problem is if someone come to the admin-panel/:type,he has to route to the create-user
by default.
I used a tricky way for this which is create root route under the admin-panel/:type
like this
2.admin-panel
2.1 /
2.2 create-user
But this doesn't work this time since the admin-panel has a parameter called type.
I want if someone comes to the admin-panel he should directed to the create-user by default. How do I achieve this?
I've to add redirect property to the admin-panel route.
Personally for these cases I use an afterEach hook in the routes file:
router.afterEach((to, from) => {
let exist = false
for (let i in this.a.options.routes) {
if (this.a.options.routes[i].name === to.name) {
exist = true
}
}
if (!exist) {
this.a.push({
name: from.name
})
}
})
You can use another hook as beforeEach (I do not remember exactly why we use after). Basically the goal is to go through the list of routes, if it does not exist, it returns you to the route you are currently on, which really means that you do not notice any changes, it just does not change the route.
I am new to vue. I would like to understand when exactly onReady() function will be fired. Vue Router docs explains this below
This method queues a callback to be called when the router has completed the initial navigation, which means it has resolved all async enter hooks and async components that are associated with the initial route.
However, I am not quite understand couple of things here,
What does initial navigation mean?
What does it mean by async enter hooks?
Please help me on this
Just in my opition, not very clear of it, hope there will be more authoritative answer.
1.When vue-router instance initialization finished.(Like when page refreshed, vue-router need create new instance.)
2.async hooks means routes that specific a async component.(When pack with webpack , it will split code into a chunk.)
{
path: '/payment',
component: () => import('#/view/payment'),
},