1

I'm not able to reference my data fields in my Vue 3 methods because of some misunderstanding in syntax and scope.

I'm using Typescript. I know this question has been asked to death but I can't for the life of me find out how to make the arrow functions of TS work to give me access to the Vue context as this

My code is simple:

  export default {
  data() {
    return {
      email: "",
      password: "",
    };
  },
  methods: {
    userLogin() {
      firebase
        .auth()
        .signInWithEmailAndPassword(this.email, this.password) //ERROR! Undefined
        .then((user: firebase.auth.UserCredential) => {
          //do stuff
        })
        .catch((error: AxiosError) => {
          //do other stuff
        });
    }

The guide here calls out this issue by saying:

An arrow function uses what is called lexical scoping. We'll get into this more in a bit, but it >basically means that the arrow function takes this from it's context.

If you try to access this from inside of an arrow function that's on a Vue component, you'll get an >error because this doesn't exist!

but it falls frustratingly short of actually providing an example fix. What do I do to access those data variables in my methods? I've tried the following and none of them work:

userLogin() {
      const self = this
      firebase
        .auth()
        .signInWithEmailAndPassword(self.email, self.password)
...

userLogin = () => {
      firebase
        .auth()
        .signInWithEmailAndPassword(this.email, this.password)
...
2
  • 1
    Your first syntax looks correct to me... What does this come up as if you console.log(this) inside userLogin? Commented Dec 12, 2020 at 5:24
  • 1
    Yeah, looks fine to me. Consider the context where you're calling the userLogin() function from. For example, if you don't have something like v-on:click="userLogin", check that the function isn't being called outside of Vue. Commented Dec 12, 2020 at 8:12

1 Answer 1

5

When using TypeScript to define a component, always use

import { defineComponent } from "vue";
export default defineComponent({
data() {
    return {
      email: "",
      password: "",
    };
  },
...

That should solve the problem.

If it doesn't, then try this:

 methods: {
    userLogin() {
         const email = this.email;
         const password = this.password;
         firebase
        .auth()
        .signInWithEmailAndPassword(email, password)
        .then((user: firebase.auth.UserCredential) => {
          //do stuff
        })
        .catch((error: AxiosError) => {
          //do other stuff
        });
    }
Sign up to request clarification or add additional context in comments.

2 Comments

Using defineComponent worked like a charm. Is this making this be the vue context to within all the Vue SFC methods/objects it wraps?
Indeed, according to the documentation To let TypeScript properly infer types inside Vue component options, you need to define components with defineComponent global method ref: v3.vuejs.org/api/global-api.html#definecomponent

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.