Défaut

Le fetch lancé dans un useEffect n’est pas annulé lors du démontage. Il peut continuer à consommer des ressources et tenter de mettre à jour l’état après le démontage. Des requêtes successives peuvent aussi créer une course où une ancienne réponse remplace la plus récente.

Correction

Créer un AbortController dans l’effet, transmettre son signal à fetch, puis appeler abort() dans la fonction de nettoyage.

useEffect(() => {
const controller = new AbortController();
let ignore = false;

async function load() {
try {
const response = await fetch(url, {
signal: controller.signal,
});

if (!response.ok) {
throw new Error(HTTP ${response.status});
}

const data = await response.json();

if (!ignore) {
setData(data);
}
} catch (error) {
if (error.name !== "AbortError" && !ignore) {
setError(error);
}
}
}

load();

return () => {
ignore = true;
controller.abort();
};
}, [url]);

Le nettoyage s’exécute au démontage et avant chaque nouvelle exécution de l’effet. AbortError doit être ignorée, car elle correspond à une annulation volontaire. Le drapeau ignore évite également qu’une réponse devenue obsolète mette à jour l’état.