问题
I am fetching data in componentDidMount and updating the state and the famous warning is appearing:
Warning: Can't call setState (or forceUpdate) 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.
My code is as follow:
componentDidMount() {
let self = this;
let apiBaseUrl = Config.serverUrl;
axios.get( apiBaseUrl + '/dataToBeFetched/' )
.then( function(response) {
self.setState( { data: response.data } );;
} );
}
What is causing this warning and what is the best way to fetch the data and update the state?
回答1:
Based on a previous answer, I have done the following which worked fine:
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 } )
}
Another better solution is to cancel the request in the unmount as follows:
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.' )
}
回答2:
You can try this:
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 :
}
回答3:
This most likely happened because the component was already unmounted before the async call finished. Meaning, your call to setState in the axios promise is being called after the component is already unmounted, perhaps because of a react-router Redirect or a change in state?
回答4:
Call setState on componentWillUnmount is the worst practice
componentWillUnmount() {
this.setState( { isMounted: false } ) // don't do this
}
来源:https://stackoverflow.com/questions/50396375/componentdidmount-cant-call-setstate-or-forceupdate-on-an-unmounted-componen