React useEffect cleanup nedir?
useEffect fonksiyonunda neden cleanup'a ihtiyaç duyarız? Component unmount olduğunda mı calısır? İnternette araştırdım ama bir türlü kafamdaki soruları çözemedim.
Evet, component unmount olduğunda çalışır. Aşağıda kaynağını verdiğim sitede olay şu şekilde açıklanmış:
React useEffect cleanup: Nasıl ve ne zaman kullanılır?
useEffect(()=>{
// effect
return () => {
// cleanup
}
},[input]);
Hiç şu hatayla karşılaştınız mı?
Can't perform a React state update 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 a useEffect cleanup function.
Mesaj, bir component unmount olup kullanılmaz hale geldikten sonra component'te bişeyler değiştirmeye çalıştığımızı söylüyor.
Bunun birçok nedeni olabilir. Ama en yaygın olarak ya bir websocket bağlantısını sonlandırmadan veya asenkron bir fonksiyon henüz sonuç dönmeden önce component'iniz unmount olmuştur.
Peki bunu nasıl çözeriz?
useEffect hook'undaki cleanup fonksiyonu
useEffect fonksiyonunda bir fonksiyon return edersek bileşenden ayrıldığımızda bu fonksiyon çalışır. Bu çok kullanışlıdır çünkü gereksiz işlemlerin yapılması veya bellek sızıntılarını önlenmesi için kullanılabilir.
websocket bağlantısının aboneliğinin iptal edildiği bir örnek:
useEffect(() => {
API.subscribe()
return function cleanup() {
API.unsubscribe()
}
});
Unmount olmuş bir bileşenin state'ini set etmeyin
Yaygın bir kullanım senaryosunda; asenkron bir fonksiyondan sonuç döndüğünde state güncellenir. Peki asenkron fonkisyon sonuç dönmeden önce component unmount olursa? Biz bu durumu kontrol etmezsek react, component unmount olsa bile state'i güncellemeye çalışır.
Aşağıdaki örnekte bir fetch isteğinden yanıt döndüğünde loading state'ini güncelliyorum.
useEffect(() => {
fetchAPI.then(() => {
setLoading(false)
})
}, [])
Ama fetchAPI'nin then fonksiyonu henüz çalışmadan önce bileşen unmount olabilir ve react yine de loading state'imi güncellemeye çalışır. Bu durumda uygulama patlamasa bile react bize uyarı verir.
Basit bir kontrolle bu sorunun önüne geçebiliriz.
useEffect(() => {
let mounted = true
fetchAPI.then(() => {
if (mounted) {
setloading(false)
}
})
return function cleanup() { mounted = false }
}, []);
Ekstra: Axios isteğini iptal edin
Axios, bir istek tamamlanmadan önce iptal etme seçeneğine sahiptir. Bu özellik bellek sızıntısının önüne geçmek için cleanup fonksiyonunda kullanışlıdır.
useEffect(() => {
const source = axios.CancelToken.source()
const fetchUsers = async () => {
try {
await Axios.get('/users', {
cancelToken: source.token,
})
// ...
} catch (error) {
if (Axios.isCancel(error)) {
console.log('Request iptal edildi.', error.message);
}
else { throw error }
}
}
fetchUsers()
return () => {
source.cancel()
}
}, [])
Kaynak: https://dev.to/otamnitram/react-useeffect-cleanup-how-and-when-to-use-it-2hbm