Search code examples
javascriptreactjsfirebaseeventslistener

Add multiple observers to this.listener to React component class


I want to add multiple observer functions to a React component. I use Firebase authentication and want to trigger actions

For this component I followed this tutorial:

export class AuthContextProvider extends React.Component {

  componentDidMount() {
    if (!this.state.firebase) {

      /** set listener whether user is signed in */
      this.listener = this.props.firebase.auth().onAuthStateChanged(
        authUser => {
          if (authUser) {
            this.setState({ authUser });
          } else {
            this.setState({ authUser: null });
          }
        },
      );

      /**
       * ########
       * Question: Can I just add another function to this.listener?
       * Will both listeners trigger the appropriate times?
       * ########
       */
      this.listener = this.props.firebase.auth().onIdTokenChanged(
        authUser => {
          if (authUser) {
            // do something
          }
        },
      );
    }
  }
}

It seemed to work in my implementation. Both events are triggered. But it seems wrong to me since I am reassigning this.listener when using .onIdTokenChanged().

How can I add both onAuthStateChanged AND onIdTokenChanged to this.listener correctly?


My question is also about this.listener. What exactly does it do? Where can I find documentation about it? Typing '"this.listener" react' shows many results about window.addEventListener. Is this an equivalent and achieves the same goal?

I assume this in this.listener refers to my class which extends React.Component. The React documentation does not mention anything about this listener property. Please correct me here if this refers to something else.


Solution

  • @Ross Allen correctly pointed out in his comment:

    this is the component instance, but listener is unrelated to React; it's an arbitrary instance variable name. You won't find anything in React documentation about it because it's not specific to React. The second time you assign this.listener = you are writing to the same variable and losing the reference to the onAuthStateChanged handler.

    The solution is to define two different arbitrary variables that are assigned to the component class:

      componentDidMount() {
        if (!this.state.firebase) {
    
          // rename to onAuthStateChangedlistener 
          this.onAuthStateChangedlistener = this.props.firebase.auth().onAuthStateChanged(
            authUser => {
              if (authUser) {
                this.setState({ authUser });
              } else {
                this.setState({ authUser: null });
              }
            },
          );
    
          // rename to onIdTokenChangedlistener 
          this.onIdTokenChangedlistener = this.props.firebase.auth().onIdTokenChanged(
            authUser => {
              if (authUser) {
                // do something
              }
            },
          );
        }
      }
    

    Now both listeners are active.