Unable to use this.$router.push(' ') inside docRef function

Kyle Wilson picture Kyle Wilson · Jun 16, 2019 · Viewed 7.7k times · Source

I am trying to use vue-router in my quasar project. this.$router.push( ' ' ) works everywhere on the page except inside this docRef block.

I found out that this.$router.push still works in the same component.

This router call works:

const userRef = this.$db.collection('users').doc(this.$fb.auth().currentUser.uid)
console.log('your id is' + this.$fb.auth().currentUser.uid)
userRef.set({
  accountUID: this.$fb.auth().currentUser.uid,
  accountChosen: true,
  accountType: 'user'
})
this.$router.push('../user/home')

This does not work (in the same component):

  var docRef = this.$db.collection('users').doc(uid)
  docRef.get().then(function (doc) {
    data = doc.data().accountType
    if (data === 'user') {
      console.log('account is users')
      console.log(data)
      this.$router.push('./user/home')
    } else if (data === 'truck') {
      console.log('account is a truck')
      this.$router.push('./truck/home')
    } else {
      console.log('in else statement')
    }
  }).catch(function (error) {
    console.log(error)
  })

Chrome Console Error

TypeError: Cannot read property '$router' of undefined
        at eval (Check.vue?a4ce:44)

Answer

acdcjunior picture acdcjunior · Jun 16, 2019

Instead of:

docRef.get().then(function (doc) {

Use:

docRef.get().then((doc) => {

Explanation

The this inside an arrow function body block refers to the current context, in your case, the Vue/component instance.

But when you use function instead of an arrow function, the {} block creates a new context, changing the semantics of this, making it point to something else than the this outside that function.

In other words, your problem happens because each function () {} has its own context (its own this), which could be set to something else. Arrow functions, OTOH, inherit the context (the this) of where it is declared. In this case, since you are declaring it inside a method, the this is the Vue instance. Using an arrow function keeps it. Using a function() does not guarantee it (the this could be set to something else, which generally is the case).

For futher details, I recommend MDN - Arrow Functions.