componentDidMount: Невозможно вызвать setState (или forceUpdate) для несмонтированного компонента - PullRequest
0 голосов
/ 17 мая 2018

Я получаю данные в componentDidMount и обновляю состояние, и появляется известное предупреждение:

Предупреждение. Невозможно вызвать setState (или forceUpdate) для неустановленного компонента. Это не работает, но это указывает на утечку памяти в вашем приложении. Для исправления отмените все подписки и асинхронные задачи в методе componentWillUnmount.

Мой код выглядит следующим образом:

componentDidMount() {
    let self = this;

    let apiBaseUrl = Config.serverUrl;
    axios.get( apiBaseUrl + '/dataToBeFetched/' )
        .then( function(response) {
            self.setState( { data: response.data } );;
        } );
}

Что вызывает это предупреждение и каков наилучший способ получить данные и обновить состояние?

Ответы [ 4 ]

0 голосов
/ 10 февраля 2019

Звоните setState на componentWillUnmount - худшая практика

componentWillUnmount() {
    this.setState( { isMounted: false } ) // don't do this
}
0 голосов
/ 19 сентября 2018

Скорее всего, это произошло потому, что компонент был отключен до завершения асинхронного вызова.Это означает, что ваш вызов setState в обещании axios вызывается после того, как компонент уже отключен, возможно, из-за перенаправления react-router или изменения состояния?

0 голосов
/ 05 февраля 2019

Вы можете попробовать это:

constructor() {
    super();
    this._isMounted = false;
}

componentDidMount() {
    this._isMounted = true;
    let apiBaseUrl = Config.serverUrl;
    this.setState( { isMounted: true }, () => {
        axios.get( apiBaseUrl + '/dataToBeFetched/' )
            .then( (response) => { // using arrow function ES6
                if( this._isMounted ) {
                    this.setState( { pets: response.data } );
                }
            } ).catch( error => {
                // handle error
        } )
    } );
}

componentWillUnmount() {
    this._isMounted = false; // equals, not :
}
0 голосов
/ 18 мая 2018

На основании предыдущего ответа я сделал следующее, что работало нормально:

constructor(props) {
   this.state = {isMounted: false}
}

componentDidMount() {
    let apiBaseUrl = Config.serverUrl;
    this.setState( { isMounted: true }, () => {
        axios.get( apiBaseUrl + '/dataToBeFetched/' )
            .then( (response) => { // using arrow function ES6
                if( this.state.isMounted ) {
                    this.setState( { pets: response.data } );
                }
            } ).catch( error => {
                // handle error
        } )
    } );
}

componentWillUnmount() {
    this.setState( { isMounted: false } )
}

Другое лучшее решение - отменить запрос в unmount следующим образом:

constructor(props) {
    this._source = axios.CancelToken.source();
}

componentDidMount() {
    let apiBaseUrl = Config.serverUrl;
    axios.get( apiBaseUrl + '/dataToBeFetched/', { cancelToken: this._source.token } )
        .then( (response) => { // using arrow function ES6
            if( this.state.isMounted ) {
                this.setState( { pets: response.data } );
            }
        } ).catch( error => {
            // handle error
    } );
}

componentWillUnmount() {
    this._source.cancel( 'Operation canceled due component being unmounted.' )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...