Lorsque vous déclenchez une Promise, il peut s'écouler quelques secondes avant qu'elle ne se résolve et d'ici là, l'utilisateur peut avoir navigué vers un autre endroit de votre application. Ainsi, lorsque la Promise se résout, setState
est exécuté sur un composant non monté et vous obtenez une erreur - tout comme dans votre cas. Cela peut également entraîner des fuites de mémoire.
C'est pourquoi il est préférable de déplacer une partie de votre logique asynchrone en dehors des composants.
Sinon, vous devrez d'une manière ou d'une autre annuler votre Promise. En alternative - en dernier recours (c'est un antipattern) - vous pouvez conserver une variable pour vérifier si le composant est toujours monté :
componentDidMount(){
this.mounted = true;
this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}
componentWillUnmount(){
this.mounted = false;
}
Je vais de nouveau souligner que c'n'est un antipattern mais cela peut être suffisant dans votre cas (tout comme ils l'ont fait avec l'implémentation de Formik
)
.
Une discussion similaire sur GitHub
EDIT:
C'est probablement comment je résoudrais le même problème (avec rien d'autre que React) en utilisant Hooks:
OPTION A:
import React, { useState, useEffect } from "react";
export default function Page() {
const value = usePromise("https://something.com/api/");
return (
{value ? value : "récupération des données..."}
);
}
function usePromise(url) {
const [value, setState] = useState(null);
useEffect(() => {
let isMounted = true; // suivre si le composant est monté
request.get(url)
.then(result => {
if (isMounted) {
setState(result);
}
});
return () => {
// nettoyage
isMounted = false;
};
}, []); // uniquement sur "didMount"
return value;
}
OPTION B: Alternativement avec useRef
qui se comporte comme une propriété statique d'une classe, ce qui signifie qu'elle ne déclenche pas de nouveau rendu du composant lors de son changement de valeur :
function usePromise2(url) {
const isMounted = React.useRef(true)
const [value, setState] = useState(null);
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
useEffect(() => {
request.get(url)
.then(result => {
if (isMounted.current) {
setState(result);
}
});
}, []);
return value;
}
// ou l'extraire pour le custom hook:
function useIsMounted() {
const isMounted = React.useRef(true)
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
return isMounted; // retourner "isMounted.current" ne fonctionnerait pas car nous retournerions un primitif non mutable
}
Exemple: https://codesandbox.io/s/86n1wq2z8
0 votes
Quel est cet avertissement je n'ai pas ce problème
0 votes
Question mise à jour
0 votes
Avez-vous promis du code asynchrone pour la récupération
0 votes
Ajoutez votre code de récupération à la question
0 votes
Voir isMounted est un Antipattern et annulation d'une requête fetch.