Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove the new firebase onAuthStateChanged listener in react

I'm implementing firebase auth in a react web app with react-router.

A user signs in (at /signin) with either Facebook or Google using the popup sign in, then if successful I route to the main app (/). In the main app component I listen for an auth state change:

  componentWillMount() {
    this.authListener = this.authListener.bind(this);
    this.authListener();
  }

authListener listens for the auth change:

authListener() {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log('user changed..', user);
        this.setState({
          User: {
            displayName: user.displayName
          }
        });
      } else {
        // No user is signed in.
        browserHistory.push('/signin');
      }
    });
  }

Everything works fine, except when I sign out (and go back to /signin) and sign in again using facebook or google. Then I get an error saying:

Warning: setState(...): Can only update a mounted or mounting component.

I suspect that the onAuthStateChanged listener from the now unmounted previous logged in state app is still running.

Is there a way to remove the onAuthStateChanged listener when the App component unmounts?

like image 249
user2248331 Avatar asked Jun 26 '16 12:06

user2248331


People also ask

What is onAuthStateChanged firebase?

According to the documentation, the onAuthStateChanged() function returns. The unsubscribe function for the observer. So you can just: var unsubscribe = firebase. auth(). onAuthStateChanged(function (user) { // handle it });

What is onAuthStateChanged used for?

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.


2 Answers

I know I am late to the game, but here's a hooks based solution:

React.useEffect(() => {
    const unsubscribe = firebase.auth().onAuthStateChanged((user) => { // detaching the listener
        if (user) {
            // ...your code to handle authenticated users. 
        } else {
            // No user is signed in...code to handle unauthenticated users. 
        }
    });
    return () => unsubscribe(); // unsubscribing from the listener when the component is unmounting. 
}, []);
like image 178
Srividya K Avatar answered Oct 03 '22 22:10

Srividya K


Any listeners that you have set up will also need to be torn down.

Your suspicions are very much on-spot.

You should use the componentWillUnmount lifecycle method to remove any leftover listeners that might pollute your app.

To clear up the listener, here's the relevant code:

Inside your authListener function you need to save a reference to the listener inside your component (it is returned to you as a result of calling firebase.auth().onAuthStateChanged). It will be a hook that will un-reference the listener and remove it.

So instead of just calling it, save the returned value as such

this.fireBaseListener = firebase.auth().onAuthStateChanged ...

And when your component un-mounts, use this code:

componentWillUnmount() {
   this.fireBaseListener && this.fireBaseListener();
   this.authListener = undefined;
}
like image 30
Elod Szopos Avatar answered Oct 03 '22 21:10

Elod Szopos