Photo by Dan-Cristian Pădureț on Unsplash

REACT HOOK SERIES

React Hooks — useEffect Nedir?

Hook konusunda seriye devam ediyoruz. Bu yazıda React içerisinde gelen useEffect Hook üzerinde duracağız.

Frontend Development With JS
5 min readApr 9, 2021

--

Bu konuya başlamadan önce serinin ilk iki yazısı olan React Hooks Nedir ? ve React Hooks Neden Çıktı ? yazılarını okumanızı öneririm..

React Hook bileşenler için ortak bir takım davranışların kanca atılarak sağlanması olduğunu anlatmıştım. Aynı aşağıdaki resimde olduğu gibi.

Bir önceki yazımızda useState bahsetmiştik. Bu yazımızda da bileşenlerin dışarıya etkisi, bileşen dışı etkileşimi yani SideEffect useEffect Hook’ları ile yapmanızı sağlar.

SideEffect kavramından Fonksiyonel Programlamada bahsetmiştik. Detay için aşağıdaki 2 yazıyı okuyabilirsiniz.

React Bileşenlerinde Network ulaşıyorsanız, DOM’a ulaşıyorsanız yani WebAPI üzerinden veya sunulan kütüphaneler ile bu bileşen dışında bir etkinizi göstermek istiyorsanız bunu useEffect içerisinde yapmanız gerekiyor.

  • Yeni bir effect ekleme.
  • Skip ederek bir sonraki durumda effect etkili olmasını sağlama
  • Effect’i temizleme

1. useEffect Nasıl Çalışıyor ?

Yapısına gelince siz React kütüphanesi içerisinden useEffect çağırırken bir callback fonkiyon geçiriyorsunuz bu callback fonksiyon bileşen her render edildikten sonra çağrılıyor(invoke) ediliyor.

console.count ve document.title bu bileşen dışındaki tarayıcı ile ilgili Console ve Document.title Etkilediği için bunu useEffect içerisinde çağırıyoruz.
https://codesandbox.io/s/useeffect-counter-fcdgp

Bu kodun çalışmasını debug ederek biraz çalışma mantığını anlayabiliriz. Örneğin ekranı refresh ettik. Counter fonksiyonu 2 defa çağrıldı useState ve useEffect ile ilgili state bağlantısı kurulup, side effect callback fonksiyonu set edildi.. 2nci yazdığında aynı fonksiyon önceki callback fonksiyonun üzerine tekrardan yazıldı… ve dönen JSX alıp ekrana bastı.. VDOM → DOM güncelledikten sonra artık bileşen SideEffect dışarı yansıtabilir dendi ve

Sonrasında sayıyı bir arttırdığımda bileşen tekrar render edilecek. Ama bileşen render fonksiyonun ilk çağrımı değil , 2nci çağrımı sonrasında yapılıyor…

Bunun nedeni şundan kaynaklanıyor diye düşünüyorum. useEffect yaptığımız callback state göre değiştirmek istersek. Arada bir render etmeyen fonksiyon çağrımı bize bu avantajı sağlar diye düşünüyorum.

Örneğin fonksiyonumuz aşağıdaki şekilde güncelleyelim. count %2 göre çıkan değerlerde farklı farklı effectler uygulamak isteyelim.

Counter kodunun %2 göre güncelledik

Aşağıda görüleceği gibi Fonksiyonun ekstradan çağrım, bazen useEffect bazende useEffect XXX çağırabilmemize olanak sağlıyor..

Counter kodunun %2 göre Cıktısı…

2. useEffect İçerisindeki değişiklik State Güncellerse Ne Olur ?

Aşağıdaki kodumuz inceliyelim. GitHub Profile bilgisi için GitHub API’den veri çekeceğiz. Burada yanlız ilginç bir durum var..

useEffect içerisinden setProfile çağırıyoruz yani State Güncellemesi yapıyoruz.

Diyebilirsiniz ki bunun ne etkisi var ?

//https://codesandbox.io/s/useeffect-infinite-loop-tczzm?file=/src/index.js:62-718

Bu durumda setState DOM güncelleyecek ve useEffect çağıracak, useEffect tekrar GitHub API’sinden ilgili profile çağıracak ve onun sonucunda tekrar state güncellenecek vs.. şeklinde sürekli bir Cyclic Infinitive Loop girmiş olacak fonksiyonumuz.

Bunu engellemek için useEffect sonuna bir scope veriyoruz. İçi boş bir array verdiğimizde [] useEffect ne olursa olsun 1 kere çağrılır oda Bileşen Initial Render dediğimiz DOM ilk çizildikten sonra..

Bileşene Input Ekleyerek buradan gelen değerle değişimine göre useEffect çağrılsın dersek burada da bir scope vermemiz gerekiyor [input] useEffect scope/bağımlılık olarak verdiğimiz için sadece input değiştiğinde çağrım gerçekleşecektir.

useEffect çağrımını belli değişkenlerin değişimine bağladık…

Önemli Not: Büyük projelerde özellikle Sunucu(server) search veya liste veri çekiyorsanız bu aşamada kullanıcının her klavye basışında input değişeceği için bu Rendering çabası Main Thread kilitleyebilir veya yavaşlatıp ekranınızın flick ederek gözükmesine neden olabilir. Bu durumları nasıl engelleyebileceğinizi … Input Alanları UI Neden Bloklar ? yazımdan okuyabilirsiniz. Burada ufak bir çözüm öneriside içeriyor.

3. useEffect İçerisindeki SideEffect Bağımlılıklarını Temizlemek.

useEffect içerisinde bir takım subscription yaptınız. Ve bileşen render artık ekrandan çıkarılsa bile bu bağımlılıklar devam edecek…

Counter örneğimizi biraz daha değiştirerek setInterval kodu ile 1 saniyede bir ekrana HELLO yazdıralım… Ve bileşeni ekrandan kaldırdığımız da setInterval çalışmasını istemiyoruz …

Bu durumda Başka bir bileşen Render edilmesine geçince bu bileşen ekrandan çıkarıldığında HELLO devam ediyor mu ?

Evet. İsteMEdiğimiz bir durum oluştu. Bileşen Render etmiyoruz ama etkisisi devam ettiriyor. Bu diğer bileşen ve Application için istenmeyen bir durum.

bileşen render edilmese bile HELLO yazmaya devam ediyor

Counter4 Bileşeni useEffect içerisinde geriye bir fonksiyon return edildiğinde bu fonksiyon useEffect callback çağrılmadan önce bu return fonksiyon çağrılır ve burada sideEffect oluşan subscription kaldırabilirsiniz.

Yukarıdaki kod çalışırken, bu bileşen rendering veya ilgili subscription eklenmiş entity değişmesi sonucu unsubscribe işlemi yapabilmenize olanacak sağlar.

Source Kod

GitHub kodu

4. Bileşende Multiple Props(Çoklu Props) etkisini useEffect ile nasıl kontrol ederiz ?

Bu kısımda bir bileşen birden fazla property alıyor ise ve bu propery değişimine göre farklı effectler oluşturmak isteniyor ise bu durumu nasıl kontrol edebiliriz ? Veya nasıl yönetiriz

Bu durumun benzeri bir test ortamı oluşturdum. https://onurdayibasi.dev/hooks-useeffect-01

Örnek 3 farklı özelliğin bileşene dışardan verilmesiyle oluşuyor.

  • Name
  • Age
  • Height

Burada amacımız dışarıdan verilen bir değişkenin değişikliğiniz sadece bir effect tarafından ele alınması diğer prop değişikliğinin efect’inin birbirini etkilememesi

Bunu yapan useEffect bir bileşende farklı bağımlılıklar ile birden fazla şekilde çoklanarak ele alınabilmesi. aşağıdaki kodda bağımlılıkların useEffect ile nasıl ele alındığını görebilirsiniz.

function User(props) {

useEffect(() => {
console.log('No filtering every render called')
})

useEffect(() => {
console.log('called once at first')
}, [])


useEffect(() => {
console.log('useEffect Name updated:' + props.name);
}, [props.name])

useEffect(() => {
console.log('useEffect Age updated:' + props.age)
}, [props.age])

useEffect(() => {
console.log('useEffect Height updated:' + props.height)
}, [props.height])


return (
<div>
My Name is {props.name} and My Age is {props.age} and I am tall {props.height}
</div>
)
}

Referanslar

https://ui.dev/

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--