2
votes

//Why this question isn't a duplicate of (How to access the correct `this` inside a callback?) : my question is a react-specific question and visitors might not mentally connect the dots between the issue raised in the above link and what I'm struggling with.

I'm trying to store the user data returned by Firebase auth's onAuthStateChanged function and store that data in state to work with it in my react app. In my app, I have the below listener:

  componentDidMount() {

    firebase.auth().onAuthStateChanged(function(user) {

      var theUser;

      if (user) {
        console.log("user is logged in!");

        theUser = user;

        this.setState({
          session: theUser
        });
        // User is signed in.
      } else {
        // No user is signed in.
        console.log("user is not logged in!")
        theUser = null;
      }
  }
}

But I get the error "TypeError: this.setState is not a function". I've tried binding "this" to componentDidMount to no avail.

2

2 Answers

4
votes

As @Jason Byrne said it seems to a problem specifying who is "this" and you can follow the approach he mentioned in his answer.

Another modern approach is to use ES6 arrow functions as they work in lexical scope, so this is determined depending on "where" it is written (which is your class):

componentDidMount() {

    firebase.auth().onAuthStateChanged(user => {

      var theUser;

      if (user) {
        console.log("user is logged in!");

        theUser = user;

        this.setState({
          session: theUser
        });
        // User is signed in.
      } else {
        // No user is signed in.
        console.log("user is not logged in!")
        theUser = null;
      }
  }
}

Also have a look here: How to access the correct `this` inside a callback?

2
votes

"this" in JavaScript can be a bit difficult, you have to be sure you know what this is referring to. Because the "this" is inside of the "function(user)" it is relative to that function... not your application as a whole. I'd have to see you whole code to be sure, but you can do something like this to hold on to a reference of your application and use that instead.

 let myApp = this;

 componentDidMount() {

    firebase.auth().onAuthStateChanged(function(user) {

      var theUser;

      if (user) {
        console.log("user is logged in!");

        theUser = user;

        myApp.setState({
          session: theUser
        });
        // User is signed in.
      } else {
        // No user is signed in.
        console.log("user is not logged in!")
        theUser = null;
      }
  }
}