Je récupère des données dans composantDidMount et met à jour l'état et l'avertissement célèbre apparaît:
Avertissement: Impossible d'appeler setState (ou forceUpdate) sur un composant non monté. Ceci est un non-op, mais cela indique une fuite de mémoire dans votre application. Pour résoudre ce problème, annulez toutes les souscriptions et les tâches asynchrones dans la méthode ComponentWillUnmount.
Mon code est le suivant:
componentDidMount() {
let self = this;
let apiBaseUrl = Config.serverUrl;
axios.get( apiBaseUrl + '/dataToBeFetched/' )
.then( function(response) {
self.setState( { data: response.data } );;
} );
}
Quelle est la cause de cet avertissement et quel est le meilleur moyen d'extraire les données et de mettre à jour l'état?
Sur la base d’une réponse précédente, j’ai effectué les opérations suivantes, qui ont bien fonctionné:
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 } )
}
Une autre meilleure solution consiste à annuler la demande lors du démontage de la manière suivante:
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.' )
}
Vous pouvez essayer ceci:
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 :
}
Cela est probablement dû au fait que le composant était déjà démonté avant la fin de l'appel asynchrone. Cela signifie que votre appel à setState
dans la promesse axios est appelé après le démontage du composant, peut-être à cause d'une redirection react-router
ou d'un changement d'état?
Appeler setState
sur componentWillUnmount
est la pire pratique
componentWillUnmount() {
this.setState( { isMounted: false } ) // don't do this
}