Это распространенная проблема, но я знаю, почему, и обычно могу быстро исправить.
Однако в этом случае я не могу размонтировать задачи в своем приложении ReactJS и GatsbyJS.
Приведенный ниже код прослушивает изменения Firebase auth, а with setState делает данные auth пользователей доступными в state
_initFirebase = false;
constructor(props) {
super(props);
this.state = {
authUser: null
};
}
firebaseInit = () => {
const { firebase } = this.props;
if (firebase && !this._initFirebase) {
this._initFirebase = true;
this.listener = firebase.onAuthUserListener(
authUser => {
localStorage.setItem('authUser', JSON.stringify(authUser));
this.setState({ authUser });
},
() => {
localStorage.removeItem('authUser');
this.setState({ authUser: null });
}
);
}
};
componentDidMount() {
this.setState({
authUser: JSON.parse(localStorage.getItem('authUser'))
});
this.firebaseInit();
}
componentDidUpdate() {
this.firebaseInit();
}
componentWillUnmount() {
this.listener && this.listener();
}
Вызывает ошибку в консоли
Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in WithAuthentication (created by Context.Consumer)
in Component (created by Layout)
in Layout (created by SigninPage)
in SigninPage (created by HotExportedSigninPage)
in AppContainer (created by HotExportedSigninPage)
in HotExportedSigninPage (created by PageRenderer)
Насколько я понимаю, у меня достаточно unmount этих setState задач внутри componentWillUnmount.
Не могли бы вы объяснить, что я мог пропустить?
this.listener вызывается из отдельного файла как firebase.onAuthUserListener.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что вы пытаетесь установить состояние после срабатывания componentWillUnmount... вы не можете установить состояние в componentWillUnmount.
Решение для вашего варианта использования:
initFirebase = false;
constructor(props) {
super(props);
this.state = {
authUser: null
};
// this prop to check component is live or not
this.isAmAlive = false;
}
firebaseInit = () => {
const { firebase } = this.props;
if (firebase && !this._initFirebase) {
this._initFirebase = true;
this.listener = firebase.onAuthUserListener(
authUser => {
localStorage.setItem('authUser', JSON.stringify(authUser));
//check component is live or not if live update the component
if (this.isAmAlive){
this.setState({ authUser });
}
},
() => {
localStorage.removeItem('authUser');
//check component is live or not if live update the component
if (this.isAmAlive){
this.setState({ authUser : null });
}
}
);
}
};
componentDidMount() {
this.isAmAlive =true;
this.setState({
authUser: JSON.parse(localStorage.getItem('authUser'))
});
this.firebaseInit();
}
componentDidUpdate() {
this.firebaseInit();
}
componentWillUnmount() {
this.isAmAlive = false;
this.listener && this.listener();
}
Я не знаком с firebase, это
this.listenerдействительно "отписка"? Иначе я не понимаю, почему вы бы назвали «слушателя» в крючке размонтирования