Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase onAuthStateChanged unsubscribe recursion

I have this code that checks to see if a user is already signed in in Firebase, if so, use Redux to dispatch an action and update the state to the current auth user.

/**
 * check to see if the user has signed in already or not
 */
function initAuth(dispatch) {
  return new Promise((resolve, reject) => {
    const unsubscribe = firebase.auth().onAuthStateChanged(
      authUser => {
        dispatch({ type: "INIT_AUTH", payload: authUser });
        unsubscribe();
        resolve();
      },
      error => reject(error)
    );
  });
}
initAuth(store.dispatch)
  .then(() => render())
  .catch(error => console.error(error));

What I am confused is, why is the unsubscribe() called within the unsubscribe? I know you can do this as in JavaScript recursion, but what's the use here? Thanks!

like image 452
zenoh Avatar asked Oct 31 '17 19:10

zenoh


People also ask

How do I unsubscribe from Firebase authentication?

So you can just: var unsubscribe = firebase. auth().

What does onAuthStateChanged do?

The module provides a method called onAuthStateChanged which allows you to subscribe to the users current authentication state, and receive an event whenever that state changes.

How to remove user from Firebase?

You can also delete users from the Authentication section of the Firebase console, on the Users page. Important: To delete a user, the user must have signed in recently. See Re-authenticate a user.


2 Answers

onAuthStateChanged takes a function as it's only argument. That function is the one that will be invoked whenever the auth state changes. So the code

function printHelloWorld() {
    console.log("Hello World")
}

firebase.auth().onAuthStateChanged(printHelloWorld)

Will print "Hello World" to the console, any time the auth state changes. But, at some later time, we want to stop that function from executing anymore, because we've already done whatever we need to. If you're familiar with event listeners, they use a pattern where to remove one, you would call something like removeEventListener. But firebase does not have a offAuthStateChanged or some such. Instead the onAuthStateChanged function returns a function to you that unsubscribes the function you originally gave it. To be clear, it does not return your original function (the one you gave it, so printHelloWorld in this example), but returns you a new function that can be used to remove the original.

So going back to the example:

function printHelloWorld() {
    console.log("Hello World")
}

var unsubscribe = firebase.auth().onAuthStateChanged(printHelloWorld)

// ... Sometime later when we are no longer interested in auth changes
unsubscribe();
// From this point forward, when the auth state changes, printHelloWorld will no longer be triggered.

Finally, suppose that you only want to have a function run on auth changes, but only one time. The simplest way to do that would be to have it run once, then unsubscribe it. So the code:

var unsubscribe = firebase.auth().onAuthStateChanged(() => {
    console.log("Hello World")
    unsubscribe()
})

means that the first time auth state changes, we will log the string, then immediately unsubscribe from further changes. So by calling the unsubscribe from within the function itself, we are just saying, run one time, then remove yourself.

Also, note that you can call unsubscribe at the beginning or end of the function, it doesn't matter. The entire function body will execute, just like any other. So calling unsubscribe won't halt the execution of the remainder of the function, or anything like that.

This is why things like

var unsubscribe = firebase.auth().onAuthStateChanged(() => {
    unsubscribe()
    // Lots of other code here...
});

is such a common pattern.

like image 102
CRice Avatar answered Oct 12 '22 23:10

CRice


If you want to listen for the changes in the auth status of the user just one time you have to do it this way:

const unsubscribe = firebase.auth().onAuthStateChanged((user) => { 
    if(unsubscribe) {
      unsubscribe();
    }
 }

It seems the listener runs twice, the first time when is created, and second time when the user actually changes his status. In the first time the unsubscribe is not defined so you to check that is defined before run it.

like image 28
user3803150 Avatar answered Oct 13 '22 00:10

user3803150