← Back to list

Kendi zustand’ımı yazdım !

Bu metin, Zustand gibi bir kütüphanenin temel bileşenlerini keşfetmenize ve arka planda dönen sihrin nasıl çalıştığını anlamanıza yardımcı…

Hakan Özoğlu in Frontend Development With JS · 2024-12-11 08:32 · 122 claps · 4.3 min read
#state-management #zustand #redux #react #global-state
Open on Medium ↗
Wiki topics: BIZ · Business Strategy 🌐 · Web Development

Kendi zustand’ımı yazdım !

Bu metin, Zustand gibi bir kütüphanenin temel bileşenlerini keşfetmenize ve arka planda dönen sihrin nasıl çalıştığını anlamanıza yardımcı olmayı amaçlıyor. Ama bir uyarı: Kendi Zustand’ınızı yazmaya kalkmayın! Zaten biri bu işi yapmış, hatalarını çözmüş ve arkasına bir topluluk toplamış. Neden tekerleği yeniden icat edesiniz ki? Projelerinizin ömrünü uzatmak istiyorsanız, sağlam ve test edilmiş araçları kullanın. Bu makale sadece eğitim amaçlıdır, state managerlerimizi yarıştırmıyoruz :)

Zustand açısından en sevdiğim özellik, her zaman bir provider ihtiyacını ortadan kaldırması ve sanki singleton bir provider varmış da tüm slice’lar oraya ekleniyormuş gibi hissettirmesiydi. Ama işin aslı öyle değil! Hazır olun, perde arkasındaki mekanizmayı keşfetmeye başlıyoruz. 🎬✨

Hatırlayın, zustand’da herşey create fonksiyonu ile bir store oluşturmakla başliyor. Slice/store/state kavramları birbirinin yerine kullanılabiliyor. oldukça karmaşık bir konu fakat biz bu andan sonra “store” diyerek diğerlerini de yeri geldikçe açıklayacağız.

Stor, yani içinde bir veya daha fazla state bulunduran ve kendisine ait mutation metotlarını da bulundurabilen bir yapı. Konu odaklı, doğru kurgulandığında store olarak alınıp başka projede de kullanılabilir. UI Bileşeni içermez, render markup içermez (içermemelidir)

platform-agnostik bir store yapısı örneği. flux yaklaşımı varsayılmıştır (verilerin adreslerinin değişimi verinin değişimine işaret eder)

platform-agnostik bir store yapısı örneği. flux yaklaşımı varsayılmıştır (verilerin adreslerinin değişimi verinin değişimine işaret eder)

Peki create fonksiyonu ile bunun ilgisi nedir, provider olmadan react render döngüsünü tetiklemesi nasıl olacak. bakalım birlikte.

Eğer elimizde bir create fonksiyonumuz olsaydı, kullanımı tam olarak böyle olacaktı, yani zustand için bu durum böyle, biz de aynısını yapacağız.

Gördüğünüz gibi create fonksiyonu yine fonksiyon türünde bir parametre alıyor, ve bu parametre olan fonksiyonun da kendine ait iki parametresi var, set ve get. get konusuna gelmeden önce, set sizin de gördüğünüz gibi, store içindeki alanları güncellemeye yarıyor, yani ne gönderdiysek o kısımları güncelliyor. sadece count gönderdiğimiz için sadece onu güncelleyecek.

O halde biraz typescript

peki şimdi bu create fonksiyonumuzu bu interface’i dışardan kabul edecek şekle getirelim.

Şimdi ise initializer’in parametresi olan set fonksiyonunun ve get fonksiyonunun türlerini oluşturalım.

state’in ilk halini fonksiyona olduğu gibi alan ve bir kısmını (değiştirilmek istenilen) bir fonksiyon tanımladık, o halde create türünü güncelleyelim.

Initializer içindeki iki parametreden set olan, StateSetFunction’u parametre olarak alıyor, void dönüyor,

get ise state’in tamamını dönüyor. Burada generic tür T, state interface ile karşılanacak.

Create fonksiyonu içinde initializer’i ilgili fonksiyonlarımızı içine göndererek çalıştırmak istediğimizde elde ettiğimiz kod bu şekilde oluyor.

Setter’i, ürettiği yeni değerleri state objesine yazacak şekilde güncelledik, bunuy yaparken “const state” kısmını “let state” yaptık ki yazma esnasında ‘state’ alanının adresini değiştirebilelim. bu daha sonra “flux” yaklaşımı ile react renderi güncellerken çok işimize yarayacak.

Buraya kadarki kısımda elimizdeki metotlar ile, elimizdeki değişkenlerin değerlerini ve adreslerini değiştirebiliyor olduk. Fakat gördüğünüz gibi bizim bu create fonksiyonu geriye bir hook dönmüyor, zustand’daki gibi içine fonksiyon alıp aldığı fonksiyona göre “slice” subscription yapan birşey yok ortada. onu da ekleyelim. hatırlarsanız zustand’da useStore(sliceFunction?) şeklinde bir yapı yaygın. Farklı API şekillerini de destekliyor olsa da, başta belirttiğim gibi yazımızın amacı temel mekanikleri kavramanıza yardımcı olmak. Herneyse.

create fonksiyonumuzu bu hale getirdik, şimdi ise yapmamız gereken useStore’un içini doldurmak. useStore fonksiyonu, bizim buradaki yani React.useState dışında tutulan bir veriye abone olmamızın ve o verinin değişimi ile renderi tetiklememizin tek giriş yeri. o halde burada bir hook kullanmak zorundayız. React render döngüsü tetiklemenin tek yolu react hooklarını extend etmekir. yani burada bize reactın açtığı kapılardan birini kullanmak zorunda olduğumuz yere geldik

[embed]useSyncExternalStore - React The library for web and native user interfacesreact.dev

Yukarıdaki hook, bunu yapmanın tek yolu değil. react 18 ile birlikte tanıtıldı. Bu yokken de bazı tricky yöntemler ile dış kaynaklara abone olunabiliyordu. Bu makalede her iki yöntemden uygulama örneği yapacağız

  1. extending useState (useSyncExternalStore kullanmaksızın): İçerde useState kullanarak store içindeki state’e abone olabiliriz. Burada selector bir fonksiyon ve bu fonksiyon her render döngüsünde hesaplanarak biryere kaydedilecek, değişimi halinde ise react’ı render’a zorlayacak birşeyler yapacağız.

Şu anda useEffect içinde boş bir fonksiyonu alıp listeners setine koyduk, yapmamız gereken ise, “setter” fonksiyonu ile birlikte, state üzerinde gerekli değişikliği yaptıktan sonra, setter’i de tetiklemek, tetiklemeliyiz ki react’a haber verelim.

Selector’e default value olarak, state’i dönen fonksiyonu atayabiliriz.

Şimdi ise custom bir equality fonksiyonuna destek verecek hale getirelim.

listener fonksiyonu içinde, prevSelected ve newSelected kıyaslaması yapıyorduk hatırlarsanız “===” yaparak. Şimdi onun yerine equalityFn çağıracağız.

Çok da karmaşık olmayan kodumuza şimdi baktığınızda, daha iyi anlamlandırmanızı umuyorum:

Ayrıca en alta bir kullanım örneği bıraktım. API olarak zustand’a benziyor fakat tabiki ede tüm özelliklerin burada gerçekleştirmedik.

Kullanım örneği

Bir sonraki bölümde ise useSyncExternalStore hook kullanarak daha kısa ne yapabiliriz ondan bahsedeceğiz.

Kodu alıp hemen denemek isteyenler için gist


메타데이터
post_id
a6785b8f8112
slug
kendi-zustandımı-yazdım-a6785b8f8112
url
https://medium.com/frontend-development-with-js/kendi-zustand%C4%B1m%C4%B1-yazd%C4%B1m-a6785b8f8112
canonical_url
https://medium.com/frontend-development-with-js/kendi-zustand%C4%B1m%C4%B1-yazd%C4%B1m-a6785b8f8112
author_url
https://medium.com/@haandev
status
ok
fetched_at
2026-07-19 00:27:16