Bir Sözü ateşlediğinizde çözülmesi birkaç saniye sürebilir ve o zamana kadar kullanıcı uygulamanızda başka bir yere gitmiş olabilir. Böylece, Promise çözüldüğünde setState
, bağlanmamış bileşen üzerinde yürütüldüğünde ve bir hata alırsınız - tıpkı sizin durumunuzda olduğu gibi. Bu aynı zamanda bellek sızıntılarına da neden olabilir.
Bu nedenle, eşzamansız mantığınızın bir kısmını bileşenlerden çıkarmak en iyisidir.
Aksi takdirde, Sözünüzü bir şekilde iptal etmeniz gerekecektir . Alternatif olarak - son çare tekniği olarak (bu bir antipattern) - bileşenin hala takılı olup olmadığını kontrol etmek için bir değişken tutabilirsiniz:
componentDidMount(){
this.mounted = true;
this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}
componentWillUnmount(){
this.mounted = false;
}
Bunu tekrar vurgulayacağım - bu bir anti-modeldir ancak sizin durumunuzda yeterli olabilir (tıpkı Formik
uygulamada yaptıkları gibi ).
GitHub'da benzer bir tartışma
DÜZENLE:
Muhtemelen aynı problemi (React dışında hiçbir şeyi olmayan) Hooks ile nasıl çözerdim :
SEÇENEK A:
import React, { useState, useEffect } from "react";
export default function Page() {
const value = usePromise("https://something.com/api/");
return (
<p>{value ? value : "fetching data..."}</p>
);
}
function usePromise(url) {
const [value, setState] = useState(null);
useEffect(() => {
let isMounted = true;
request.get(url)
.then(result => {
if (isMounted) {
setState(result);
}
});
return () => {
isMounted = false;
};
}, []);
return value;
}
SEÇENEK B: Alternatif olarak, bununla useRef
bir sınıfın statik özelliği gibi davranan , yani değeri değiştiğinde bileşeni yeniden oluşturmadığı anlamına gelir:
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;
}
function useIsMounted() {
const isMounted = React.useRef(true)
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
}
Örnek: https://codesandbox.io/s/86n1wq2z8