Vuex: How to get variable in store, in vue-router's canActivate function

Created on 20 Mar 2016  路  8Comments  路  Source: vuejs/vuex

Hi guys can someone give a hand with this?

Let me show you the code:

getters.js

export const user = state => {
    return state.user
}

Index.vue

<template>
    <pre>{{ user | json }}</pre>
</template>

<script>
    import { logout } from '../vuex/actions'
    import { user } from '../vuex/getters'
    export default {
        vuex: {
            getters: {
                user
            },
            actions: {
                logout
            }
        },
        route: {
            canActivate(transition) {
                console.log(user)
                if (user.authenticated) {
                    transition.redirect('/login')
                } else {
                    transition.next()
                }
            }
        }
    }
</script>

Index.vue returns

{
  "data": {},
  "authenticated": false
}

And returns this in the console, from console.log(user) inside the canActivate function

function user(state) {
    return state.user;
}

As you can see inside canActivate user return the function itself, and in the rest of the code, user returns the data

Thanks for any help.

Most helpful comment

To the original question: canActivate is called before the instance is even created - so it doesn't have access to a this context.

There are several ways around this:

  1. if you do it in activated it should work as expected.
  2. you can just import the store in your component and check store.state.
  3. or, access the store as this.$root.$store...

All 8 comments

Well, I solved the original problem with:

route: {
    canActivate(transition) {
        if (localStorage.getItem('token')) {
            transition.next()
        } else {
            transition.redirect('/login')
        }
    }
}       

But the issue still open

You need to access it like this.user, instead of user.

@azamat-sharapov thank you for your answer. I tried this console.log(this.user) inside the canActivate() and returns Uncaught TypeError: Cannot read property 'user' of null

If this is null inside router hook, then there should be something wrong in your code (or many some bug), please provide reproduction.

@azamat-sharapov Hope this can help

main.js

import Vue from 'vue'
import VueRouter from 'vue-router'

import App from './components/App.vue'
import Index from './components/Index.vue'
import Login from './components/Login.vue'

Vue.use(VueRouter)

export var router = new VueRouter()

router.map({
    '/': {
        component: Index
    },
    '/login': {
        component: Login
    }
})

router.start(App, '#app')

App.vue

<template>
    <router-view></router-view>
</template>

<script>
    import store from '../vuex/store'
    import { getUser } from '../vuex/actions'
    export default {
        store: store,
        ready() {
            if (localStorage.getItem('user_token')) {
                this.getUser()
            }
        },
        vuex: {
            actions: {
                getUser
            }
        }
    }
</script>

Your code has nothing related to original issue, this is why we ask to provide reproduction. You can try jsfiddle or webpackbin.

To the original question: canActivate is called before the instance is even created - so it doesn't have access to a this context.

There are several ways around this:

  1. if you do it in activated it should work as expected.
  2. you can just import the store in your component and check store.state.
  3. or, access the store as this.$root.$store...

@azamat-sharapov @yyx990803 thank you both for the help. I resolved it importing the store and getting the data through store.state

Was this page helpful?
0 / 5 - 0 ratings