Как удалить новую firebase onAuthStateChanged слушателя в реакции

Я использую firebase auth в интерактивном веб-приложении с помощью реагирующего маршрутизатора.

Пользователь подписывает (в/подписи) с Facebook или Google с помощью всплывающего окна, а затем, если успешно, я направляюсь в основное приложение (/). В основном компоненте приложения я слушаю изменение состояния auth:

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

authListener прослушивает смену auth:

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');
      }
    });
  }

Все работает отлично, за исключением случаев, когда я выхожу (и возвращаюсь к /signin ) и снова запишусь, используя facebook или google. Затем я получаю сообщение об ошибке:

Предупреждение: setState (...): может обновлять только установленный или монтируемый компонент.

Я подозреваю, что прослушиватель onAuthStateChanged из ранее отключенного ранее зарегистрированного приложения состояния все еще работает.

Есть ли способ удалить прослушиватель onAuthStateChanged, когда компонент приложения отключается?

Ответ 1

Любые слушатели, которые вы создали, также должны быть снесены.

Ваши подозрения очень много на месте.

Вы должны использовать метод жизненного цикла componentWillUnmount, чтобы удалить оставшихся слушателей, которые могут загрязнить ваше приложение.

Чтобы очистить слушателя, вот соответствующий код:

Внутри вашей функции authListener вам необходимо сохранить ссылку на слушателя внутри вашего компонента (он возвращается вам в результате вызова firebase.auth().onAuthStateChanged). Это будет крючок, который отключит прослушиватель и удалит его.

Поэтому вместо того, чтобы просто вызвать его, сохраните возвращаемое значение как таковое

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

И когда ваш компонент не монтируется, используйте этот код:

componentWillUnmount() {
   this.fireBaseListener && this.fireBaseListener();
   this.authListener = undefined;
}

Ответ 2

@Justin, потому что onAuthStateChanged возвращает функцию, чтобы вы могли использовать ее для очистки слушателя... this.fireBaseListener = firebase.auth().onAuthStateChanged

документы: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged

Возвращает ненулевое значение firebase.Promise, содержащее ненулевой массив строк

Ответ 3

Вместо проверки функции onAuthStateChanged() внутри componentDidMount() вы можете проверить подписку следующим образом.

componentWillMount() {
    //following line will help you to setState() but not required
    let set =  this  

    //this is our trick
    this.unsubscribe  = firebase.auth().onAuthStateChanged(user => {
        if (!user) {
            //navigate to guest stack
            //actually im using react-navigation
            set.props.navigation.navigate('Guest'); 
        } else {
            //set current user to state 
            set.setState({
                user: user,
                loading: false
            })
        }
    });
}

//What you have to do next is unsubscribe ;) 
componentWillUnmount() {
    this.unsubscribe();
}