desicne
desicne

Reputation: 861

Vue-router 2 changes route but does not update the view?

I have a login issue with website that uses:

In routes.js I have a simple interceptor setup

router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!router.app.auth.isUserLoggedIn) {
        next({
            path: '/login',
            query: { redirect: to.fullPath }
        })
    } else {
        next()
    }
} else {
    next() // make sure to always call next()!
}

})

And in login.vue,which handles the login page logic after using Google API only for login succeeds I call this:

this.login(userData).then( 
    () => this.$router.push(this.redirectToAfterLogin), // Login success
    () => {} // Login failed
)


mounted: function(){
if (this.auth.isUserLoggedIn){
            // Let's just redirect to the main page
            this.$router.push(this.redirectToAfterLogins)
        }else{
            Vue.nextTick(() => {
                this.loadGooglePlatform()
            })}}


computed: {
        redirectToAfterLogin: function() {
            if (this.$route.query.redirect){
                return this.$route.query.redirect
            }else{
                return '/'
            }
        }
    }

router.js

var VueRouter = require('vue-router')

// Router setup
export const router = new VueRouter({
    linkActiveClass: "is-active",
    mode: 'history',
    saveScrollPosition: true,
    routes: [
        { path: '', name: 'root', redirect: '/home' },
        { path: '/login', name: 'login', meta: { loadingNotRequired: true }, component: require('./pages/login.vue') },
        { path: '/logout', name: 'logout', meta: { loadingNotRequired: true }, component: require('./pages/logout.vue') },
        { path: '/home', name: 'home', title: 'Home', redirect: '/home/random', component: require('./pages/home.vue'),
            children: [
                { path: 'random', name: 'random', meta: { requiresAuth: true }, title: 'Random', component: require('./pages/random.vue') }
            ]  
        }
    ]
})

// Redirect to login page if not logged In
router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        // this route requires auth, check if logged in
        // if not, redirect to login page.
        if (!router.app.auth.isUserLoggedIn) {
            next({
                path: '/login',
                query: { redirect: to.fullPath }
            })
        } else {
            next()
        }
    } else {
        next() // make sure to always call next()!
    }
})

Now here this.login is just the call to vuex, to update the logged in user.

What happens is that after login, URL changes to /home, but the DOM does not update!

Only way that successfully changed the DOM was forcing location.reload() and that is not what I want to do, as it loses my dynamically loaded G scripts in Head.

Any idea on what to do to force the view to update DOM?

NOTE: it happens only on the first login of user, if he logs out and back-in, the redirecting is fine

Upvotes: 18

Views: 18935

Answers (4)

Lucile Fievet
Lucile Fievet

Reputation: 509

Maybe you should set the redirectToAfterLogin function into methods, like this it will be recalculated each times. The computed will be modified only if used v-model changed. To stick to the meaning of the function name, I would set the router push inside.

login.vue :

mounted: function(){
   if (this.auth.isUserLoggedIn){
            // Let's just redirect to the main page
            // this.$router.push(this.redirectToAfterLogins)
            this.redirectToAfterLogins()
   }else{
            Vue.nextTick(() => {
                this.loadGooglePlatform()
            })
   }
},
// computed: {
methods: {
    this.login(userData).then( 
       // () => this.$router.push(this.redirectToAfterLogin), // Login success
       () => this.redirectToAfterLogin(), // Login success
       () => {} // Login failed
    ),
    redirectToAfterLogin: function() {
            
        if (this.$route.query.redirect){
            // return this.$route.query.redirect
            this.$router.push(this.$route.query.redirect)
        }else{
            // return '/'
            this.$router.push('/')
        }
    }
}

"However, the difference is that computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed. This means as long as message has not changed, multiple access to the reversedMessage computed property will immediately return the previously computed result without having to run the function again."

methods vs computed and filters :

Upvotes: 0

Abhay
Abhay

Reputation: 6760

Not a perfect solution may be, as it is going to recreate the component but it will work for every case when having same route & needs to update the component.

Just update the <router-view/> or <router-view></router-view> with

<router-view :key="$route.fullPath"></router-view>

Upvotes: 12

silang
silang

Reputation: 31

I have the same problem "URL changes to /home, but the DOM does not update".
In my project, the tag "transition" maked the problem.
Hope it is helpful!

Upvotes: 1

adri
adri

Reputation: 21

Vue re-uses components where possible. You should use beforeRouteUpdate to react to a route switch that uses the same component.

Upvotes: 2

Related Questions