componentDidMount:无法在卸载的组件上调用setState(或forceUpdate)

时间:2018-05-17 16:29:05

标签: reactjs axios

我在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 :(得分:7)

根据之前的回答,我做了以下哪些工作正常:

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

另一个更好的解决方案是在卸载中取消请求,如下所示:

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

答案 1 :(得分:1)

您可以尝试以下方法:

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 :
}

答案 2 :(得分:0)

这很可能是由于异步调用完成之前已经卸载了组件而导致的。意思是,您是在卸载了组件之后调用了axios promise中对setState的调用,可能是由于react-router重定向或状态改变了?

答案 3 :(得分:0)

setState上致电componentWillUnmount是最糟糕的做法

componentWillUnmount() {
    this.setState( { isMounted: false } ) // don't do this
}