簡體   English   中英

componentDidMount:無法在卸載的組件上調用setState(或forceUpdate)

[英]componentDidMount: Can't call setState (or forceUpdate) on an unmounted component

我在componentDidMount中獲取數據並更新狀態,並出現着名的警告:

警告:無法在卸載的組件上調用setState(或forceUpdate)。 這是一個無操作,但它表示應用程序中存在內存泄漏。 要修復,請取消componentWillUnmount方法中的所有訂閱和異步任務。

我的代碼如下:

componentDidMount() {
    let self = this;

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

導致此警告的原因是什么是獲取數據和更新狀態的最佳方法?

基於之前的答案,我做了以下工作:

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

你可以試試這個:

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

這很可能是因為在異步調用完成之前已經卸載了組件。 這意味着,在組件已經卸載之后,您正在調用對axios promise中的setState的調用,可能是因為react-router Redirect或狀態react-router了變化?

componentWillUnmount上調用setState是最糟糕的做法

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM