Je reçois un message d'erreur en raison d'un problème de méthode asynchrone. Je vois dans mon terminal:
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.
- node_modules/fbjs/lib/warning.js:33:20 in printWarning
- node_modules/fbjs/lib/warning.js:57:25 in warning
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:12196:6 in warnAboutUpdateOnUnmounted
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:13273:41 in scheduleWorkImpl
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:6224:19 in enqueueSetState
- node_modules/react/cjs/react.development.js:242:31 in setState
* router/_components/item.js:51:16 in getImage$
- node_modules/regenerator-runtime/runtime.js:62:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:296:30 in invoke
- ... 13 more stack frames from framework internals
J'ai remarqué que cela indiquait spécifiquement le getImage$
Voici le code que j'utilise pour cette section:
export default class extends Component {
constructor(props) {
super(props);
const { item } = props
const bindThese = { item }
this.boundActionCreators = bindActionCreators(bindThese)
this.state = {
image: require('../../static/logo.png'),
ready: false,
showOptions: this.props.showOptions
}
this.getImage = this.getImage.bind(this)
this.renderNotAdmin = this.renderNotAdmin.bind(this)
this.renderAdmin = this.renderAdmin.bind(this)
this.handleOutOfStock = this.handleOutOfStock.bind(this)
}
async getImage(img) {
let imgUri = await Amplify.Storage.get(img)
let uri = await CacheManager.get(imgUri).getPath()
this.setState({
image: { uri },
ready: true
})
}
componentDidMount() {
this.getImage(this.props.item.image)
}
J'essaie de comprendre comment utiliser un componentWillUnmount
avec cette méthode asynchrone. Comment je m'y prends?
Merci!
Vous pouvez utiliser le motif isMounted
React pour éviter les fuites de mémoire ici.
Dans votre constructeur:
constructor(props) {
super(props);
this._isMounted = false;
// rest of your code
}
componentDidMount() {
this._isMounted = true;
this._isMounted && this.getImage(this.props.item.image);
}
dans votre componentWillUnmount
componentWillUnmount() {
this._isMounted = false;
}
En toi getImage()
async getImage(img) {
let imgUri = await Amplify.Storage.get(img)
let uri = await CacheManager.get(imgUri).getPath()
this._isMounted && this.setState({
image: { uri },
ready: true
})
}
Une approche recommandée pour utiliser Axios qui repose sur un modèle de promesse annulable. Ainsi, vous pouvez annuler tout appel réseau tout en démontant le composant avec son cancelToken subscription
. Voici une ressource pour Annulation Axios
De la blog React
Définissez simplement une propriété _isMounted sur true dans composantDidMount et définissez-la sur false dans composantWillUnmount. Utilisez cette variable pour vérifier le statut de votre composant.
On ajoute qu'idéalement, le problème pourrait être résolu en utilisant des rappels annulables, bien que la première solution semble appropriée ici.
Ce que vous ne devriez absolument pas faire est d’utiliser la fonction isMounted (), qui peut être obsolète.
Vous devez définir this.mounted = false dans la méthode ComponentWillUnmount () et this.mounted = true dans la méthode ComponentDidMount ().
La mise à jour de setState est conditionnelle en fonction de la nécessité de déclarer dans la méthode composantDidMount ().
componentDidMount() {
this.mounted = true;
var myVar = setInterval(() => {
let nextPercent = this.state.percentage+10;
if (nextPercent >= 100) {
clearInterval(myVar);
}
if(this.mounted) {
this.setState({ percentage: nextPercent });
}
}, 100);
}
componentWillUnmount(){
this.mounted = false;
}