- React'te durum, özellikle nesneler ve diziler için, doğrudan mutasyon yerine setter'lar aracılığıyla güncellemeler yapılarak, değiştirilemez olarak ele alınmalıdır.
- Durum güncellemeleri eşzamansızdır ve toplu olarak yapılabilir; bu nedenle fonksiyonel güncelleyicilerin kullanılması, zamanlayıcılarda, kapanışlarda ve hızlı etkileşimlerde eski durum sorunlarını önler.
- Hook'larla (useState, useRef ve benzerleri) çalışan fonksiyonel bileşenler modern standarttır; React.memo ve Immer gibi araçlar ise performans ve iç içe veri konusunda yardımcı olur.
- Özellikler ve durumun net bir şekilde ayrılması ve yukarıdan aşağıya veri akışı modeli, uygulamalar ölçeklendikçe bileşen davranışının öngörülebilir kalmasını sağlar.
React'te durum (state) kavramı, ilk bakışta basit görünse de uygulamanız büyüdükçe hızla karmaşıklaşan kavramlardan biridir. Küçük bir sayaçla başlarsınız, sonra birdenbire çok sayıda form alanıyla, eşzamansız güncellemelerle, iç içe nesnelerle ve her şey aynı anda yeniden oluşturulduğunda ortaya çıkan performans sorunlarıyla boğuşmak zorunda kalırsınız. Durumu derinlemesine anlamak, "React kullanan" birini, gerçek dünya React uygulamalarını ölçeklendirebilen ve hata ayıklayabilen birinden ayıran şeydir.
Bu kılavuzda, sınıf bileşenlerinden ve yaşam döngüsü yöntemlerinden modern Hook'lara ve değişmez güncellemelere kadar React'in mevcut durumunu (kelime oyununa dikkat) adım adım inceleyeceğiz. Ayrıca, eşzamansız güncellemeler, eski kapanışlar, useState yerine useRef'i ne zaman kullanacağınız ve kullanıcı arayüzünüzü nasıl tahmin edilebilir tutacağınız gibi incelikli ancak kritik konulara da değineceğiz. Amaç, bileşenlerinizin tam olarak beklediğiniz gibi davranmasını sağlayacak net bir zihinsel model oluşturmaktır.
Sahne donanımından sahne dekoruna: Ne gerçekten nereye ait?
Her React bileşeninin temelinde iki ana veri kaynağı bulunur: props ve state. destekler Üst bileşenden aktarılan değerler, o bileşenin render işlemi boyunca sabit kalırken, belirtmek, bildirmek Bu, bileşenin kendisine aittir ve onun tarafından kontrol edilir ve zaman içinde değişen veriler için tasarlanmıştır.
Genel bir kural olarak şunu söyleyebiliriz: Eğer veriler dışarıdan yapılandırılıyorsa ve bu bileşende değişmiyorsa, bu bir prop'tur; eğer bileşenin bu verileri izlemesi ve güncellemesi gerekiyorsa, bu bir state'tir. Yanıp sönen bir metin bileşenini hayal edin: gerçek metin bir kez sağlanır (bir prop), ancak şu anda gösterilip gösterilmediği sürekli olarak değişir (state). Bu ayrım, React'in veri akışınızı öngörülebilir ve tek yönlü tutmasını sağlar.
React, durumun onu kontrol etmesi gereken en yakın ortak atada bulunduğu, yukarıdan aşağıya (tek yönlü) bir veri akışını teşvik eder. Üst bileşen, durumu tutabilir ve değerleri alt bileşenlere özellik (props) olarak aktarabilir; alt bileşenler bu değerleri işleyebilir veya dönüştürebilir, ancak bu değerlerin başlangıçta durumdan mı, diğer özelliklerden mi yoksa kod içine sabitlenmiş değerlerden mi geldiğini bilmelerine gerek yoktur.
Bu nedenle devletin sıklıkla "yerel" veya "kapsüllenmiş" olarak tanımlandığını duyarsınız. Bir durumun parçasına sahip olan bileşen dışında kimse onu değiştiremez ve bu durumdan türetilen herhangi bir kullanıcı arayüzü, özellikler (props) aracılığıyla aşağı doğru akar. Durum bilgisi içeren ve içermeyen (saf) bileşenleri serbestçe birleştirebilirsiniz ve bir şeyin durum bilgisi içerip içermediği, zaman içinde değişebilen bir uygulama detayı olarak kabul edilir.
Sınıf bileşenleri: eski usulde durum ve yaşam döngüsü
Hooks'tan önce, React'te durum ve yaşam döngüsü yöntemlerini kullanmanın tek yolu ES6 sınıf bileşenleriydi. Modern uygulamaların çoğu fonksiyonel bileşenlere dayanıyor olsa da, birçok kod tabanında hala sınıf bileşenlerini göreceksiniz (ve bazen bunları koruyacaksınız), bu nedenle nasıl çalıştıklarını anlamak önemlidir.
Basit bir fonksiyon bileşenini dönüştürmek için Clock Bir sınıfa kaydolmak için birkaç mekanik adımı izlersiniz. Bir sınıfı genişleten bir sınıf oluşturuyorsunuz. React.Component, ekle render() yöntem, fonksiyon gövdesini içine taşı render, değiştir props 'da this.propsve orijinal fonksiyonu silin. React render etmeye devam ettiği sürece sorun yok. <Clock /> Aynı DOM düğümüne yerleştirildiğinde, o sınıfın tek bir örneğini yeniden kullanır.
Bir sınıfa yerel durum eklemek, bir kurucu fonksiyon tanımlamak ve başlangıç değerini atamak anlamına gelir. this.state nesne. Örneğin, bir şeyi taşıyabilirsiniz. date Prop'lardan gelen değeri state'e aktarmak için, bir kurucu metot ekleyerek bu işlemi gerçekleştirin. super(props) ve kümeler this.state = { date: new Date() }daha sonra herhangi bir kullanımın değiştirilmesi this.props.date in render() 'da this.state.dateUnutmayın ki, sınıf bileşenlerinde yalnızca doğrudan atama yapmalısınız. this.state yapıcının içinde.
Yaşam döngüsü yöntemleri, React'in bir bileşenin yaşam döngüsünün belirli noktalarında çağırdığı özel sınıf yöntemleridir. Bir bileşen ilk kez DOM'a eklendiğinde (mount edildiğinde), React bir çağrı yapar. componentDidMount()Kaldırıldığında (bağlantısı kesildiğinde), React çağrı yapar. componentWillUnmount()Klasik saatli zamanlayıcı örneğinde, bir zamanlayıcı kurarsınız. componentDidMount ve bunu temizleyin componentWillUnmountzamanlayıcı kimliğini saklayarak this (Örneğin this.timerId) ve arama this.setState() Zamanı güncellemek için her saniye.
Bu saatin tipik yaşam döngüsü şöyle görünür: React, durumu başlatmak için yapıcıyı çağırır, ardından render() DOM'u oluşturmak için, daha sonra componentDidMount() Zamanlayıcıyı başlattığınız yer. Zamanlayıcı her çalıştığında, çağırırsınız. setState()Bu işlem, bir güncellemeyi sıraya alır ve tetikler. render() Yeni durumla birlikte. Bileşen kaldırıldıktan sonra, componentWillUnmount() Zamanlayıcıyı sıfırlayarak kaynak israfını önler.
Sınıflarda devlet yönetimini doğru bir şekilde yürütmek aynı zamanda üç önemli kurala uymak anlamına da gelir. setState. Mutasyona uğramamalısınız. this.state Doğrudan söylemek gerekirse, güncellemelerin eşzamansız ve toplu olarak yapılabileceğini ve güncellemelerin yüzeysel olarak birleştirildiğini (yalnızca üst düzey durum anahtarlarının birleştirildiğini, derin iç içe geçmiş nesnelerin birleştirilmediğini) hatırlamanız gerekir.
Durum yönetimini doğru kullanma: mutasyonlar, eşzamansız güncellemeler ve veri akışı
Yeni başlayanlar için en büyük kafa karışıklığı kaynaklarından biri şudur: setState (ve Hook eşdeğeri) durumu hemen güncellemez ve durum nesnelerini asla yerinde değiştirmemelisiniz. React, performans için genellikle birden fazla güncellemeyi birlikte gruplandırır, bu nedenle her ikisi de this.state Sınıflardaki ve Hooks'taki durum değişkenlerindeki bilgiler, güncellemeyi planladıktan hemen sonraki nihai durumu yansıtmayabilir.
Durumu doğrudan değiştirmek, örneğin yapmak gibi this.state.count++ Veya bir durum nesnesinin özelliklerini değiştirmek, React'in değişiklik algılamasını atlar ve bileşenlerin eski değerlerde takılı kalmasına neden olabilir. React, state'teki herhangi bir nesneyi salt okunur olarak ele almanızı bekler. Mevcut nesneleri değiştirmek yerine, istediğiniz değişikliklerle yeni bir nesne veya dizi oluşturup bunu state güncelleyiciye iletirsiniz.
Durum güncellemeleri eşzamansız olabileceğinden, bir önceki durumdan bir sonraki durumu hesaplarken dikkatli olmalısınız. Derslerde, buna benzer bir şey. this.setState({ count: this.state.count + 1 }) Birden fazla güncelleme toplu olarak yapıldığında yanlış sonuçlar ortaya çıkabilir. Çözüm, fonksiyonel formu kullanmaktır: this.setState((prevState, props) => ({ count: prevState.count + 1 }))Bu, en güncel durum anlık görüntüsüyle çalıştığınızdan emin olmanızı sağlar.
Hook'larda da aynı durum geçerlidir: Güncelleyiciyi bir değer yerine bir fonksiyonla çağırabilirsiniz. Örneğin, setCount(prev => prev + 1) Yeni değerin önceki değere bağlı olması veya güncellemelerin daha sonra çalışan zamanlayıcılar veya olay işleyicileri içinde gerçekleşmesi olasılığı durumunda, sayacı artırmanın daha güvenli yolu budur.
Durum "yerel" olsa da, durum değişikliğinin etkisi her zaman bileşen ağacında aşağı doğru yayılır. Bir durum güncellemesiyle tetiklenen üst bileşenin yeniden oluşturulması, varsayılan olarak tüm alt bileşenlerini de yeniden oluşturur. Bu yukarıdan aşağıya veri akışı, React'in temel zihinsel modelinin temelidir: en üstte tek bir doğruluk kaynağı, altta ise ondan türetilen kullanıcı arayüzü.
Modern React: Hook'lar ve fonksiyonel bileşenler
React 16.8'den beri Hooks, fonksiyonel bileşenlerde durum ve yan etkileri yönetmenin standart yolu haline geldi. Sınıf bileşenlerinin sahip olduğu (ve daha fazlasını) yeteneklerin aynısını, sınıf yazmanıza veya bunlarla uğraşmanıza gerek kalmadan kullanmanıza olanak tanırlar. this ve yaşam döngüsü yöntemlerini açıkça kullanın. Modern JavaScript'in istikrarlı durumu.
Fonksiyonel bileşenler artık React kod tabanlarında varsayılan stil haline geldi. Yazmak yerine class Example extends React.ComponentŞöyle basit bir fonksiyon tanımlarsınız: function Example() { return <div />; }Durum, yan etkiler veya referanslara ihtiyacınız olduğunda, React'e fonksiyonlar aracılığıyla "bağlanırsınız". useState, useEffect hem de useRefHook'lar sınıfların içinde kullanılamaz ve Hook Kurallarına uymalıdır (her zaman bileşeninizin en üst seviyesinde çağrılmalı, asla döngülerde veya koşullarda kullanılmamalıdır).
MKS useState Hook, bir fonksiyon bileşenine yerel durum eklemenin en basit yoludur. Başlangıç değerini argüman olarak alır ve bir çift döndürür: mevcut durum değeri ve bir ayarlayıcı (setter). Dizi ayrıştırması sayesinde genellikle şöyle bir şey yazarsınız: const = useState(0)React, yeniden render işlemleri arasında bu durumu korur; bu da fonksiyonun birçok kez çağrılabileceği ancak durum değerinin hatırlanacağı anlamına gelir.
Sınıf durumunun aksine, sakladığınız değer useState Nesne olması gerekmez. Veriye uygun olan her şeyi, sayıları, dizeleri, mantıksal değerleri, dizileri veya nesneleri saklayabilirsiniz. Birden fazla bağımsız değere ihtiyacınız varsa, ilgili fonksiyonu çağırabilirsiniz. useState birkaç kez (örneğin, age, fruit, todosAlternatif olarak, tek bir nesne saklayabilir ve içinde birden fazla özelliği yönetebilirsiniz, ancak güncelleme yaparken değişmezlik kurallarına uymanız gerekir.
setter fonksiyonunu çağırdığınızda, bu fonksiyon tarafından döndürülen fonksiyon devreye girer. useStateDeğeri eş zamanlı olarak değiştirmiyorsunuz; tıpkı diğer yöntemlerde olduğu gibi bir güncellemeyi sıraya alıyorsunuz. setState derslerde. Bir sonraki render işleminde, React bileşeninizin yeni durum değerini verir. Bu nedenle, aynı senkron fonksiyon içinde setter'ı çağırdıktan hemen sonra durumu okumak size hala eski değeri verecektir.
Nesnelerin ve iç içe geçmiş verilerin durum yönetimi
React, nesneler ve diziler de dahil olmak üzere herhangi bir JavaScript değerini state'e koymanıza olanak tanır, ancak bunları değiştirilemez anlık görüntüler olarak ele almalısınız. Sayılar ve dizeler gibi temel değerler zaten değiştirilemez, ancak nesneler ve diziler teknik olarak değiştirilebilir; ancak, bunların değiştirilmesi React'in varsayımlarını bozar ve bileşenlerin güncellenmemesi gibi ince hatalara yol açabilir.
Şöyle bir durum nesnesini ele alalım: { x: 0, y: 0 } Bir işaretçi konumunu temsil eder. Eğer yazarsan position.x = event.clientX Doğrudan, mevcut nesneyi değiştirdiniz. React, değerin değiştiğini bilmiyor çünkü setter'ı hiç çağırmadınız, bu yüzden yeniden render etmeyecek ve kullanıcı arayüzünüz takılı kalacak. Doğru yaklaşım şudur: setPosition({ x: event.clientX, y: event.clientY })Bu, tamamen yeni bir nesne oluşturur ve React'e bu nesneyle render işlemi yapmasını söyler.
Yeni oluşturulan nesnelerin yerel mutasyonu tamamen normaldir. Örneğin, yeni bir nesneyi adım adım oluşturabilirsiniz: const next = { ...prev }; next.city = 'Paris'; olduğu sürece next Zaten mevcut durumda değildi. Değişiklik, ancak daha önceki bir durum anlık görüntüsünde zaten kullanılmakta olan bir nesneyi değiştirdiğinizde sorun haline gelir, çünkü uygulamanızın diğer bölümleri hala o eski değere bağlı olabilir.
Bir nesnenin yalnızca bir bölümünü güncellerken geri kalanını korumak için genellikle nesne yayma sözdizimini kullanırsınız. Örneğin, bir form durumu nesnesi için { firstName, lastName, email }Örneğin, girdi değişikliklerini şuna benzer bir şeyle ele alabilirsiniz. setPerson({ ...person, : event.target.value })Bu işlem eski özellikleri kopyalar, ardından yalnızca değişen özelliği üzerine yazar. Yayılım sığdır, bu nedenle iç içe nesneler daha fazla dikkat gerektirir.
Derinlemesine iç içe geçmiş nesneler, değiştirdiğiniz yolun her seviyesinde yeni kopyalar oluşturmanız gerektiğinden, hızla uzun ve ayrıntılı güncelleme koduna yol açabilir. Örneğin, person.artwork.city değişiklikler, yapardınız setPerson({ ...person, artwork: { ...person.artwork, city: 'London' } })Aslında, "iç içe nesne" diye bir şey yok; birbirine işaret eden ayrı nesneler var, bu nedenle birden fazla üst nesne aynı alt nesneye işaret ediyorsa ve siz onu değiştirirseniz, aynı anda birden fazla yerdeki veriyi değiştirmiş olursunuz.
Sürekli iç içe sayfalar yazıyorsanız, durum şeklinizi düzleştirmeyi veya Immer gibi bir yardımcı kütüphane kullanmayı düşünebilirsiniz. Immer, değiştirilebilir (mutatif) görünen kod yazmanıza olanak tanır (örneğin...). draft.artwork.city = 'London'(Bu işlem arka planda sizin için yeni, değiştirilemez bir kopya oluşturur.) React'te Immer'ı Hooks ile şu şekilde eşleştirebilirsiniz: useImmer itibaren use-immer paketi.
Uygulamada durum: formlar, zamanlayıcılar ve kullanıcı girişi
Gerçek dünya uygulamalarında, nadiren sadece sayaçlar için durum yönetimi yaparsınız; kullanıcı girdilerini, API yanıtlarını ve yükleme, hata ve başarı gibi kullanıcı arayüzü "modlarını" yönetirsiniz. React ile ilgili temel zihniyet değişikliği, "DOM'u manipüle etmemeniz" (örneğin, "bu düğmeyi devre dışı bırak") yerine, her durum için kullanıcı arayüzünün nasıl görünmesi gerektiğini tanımlamanız ve ardından durumu güncellemenizdir.
Örneğin, bir sınav veya form bileşeni şunları takip edebilir: status arasında geçiş yapan bir durum 'typing', 'submitting' hem de 'success'. JSX kodu, gönderim sırasında gönder düğmesini koşullu olarak devre dışı bırakır ve cevap doğru olduğunda başarı mesajı gösterir. Zorunlu DOM yöntemlerini asla çağırmazsınız; React, yeni durumla yeniden render eder ve görsel çıktı değişir.
Form alanlarını ele alırken birçok geliştirici, sınıf durumu birleştirme ile farklı yaklaşımlar arasındaki farkı ilk kez burada fark eder. useState davranışı. Bir sınıfta, setState Geçirdiğiniz nesneyi mevcut durum nesnesine birleştirir, böylece bir alanı güncellemek diğerlerini silmez. useStateGüncellemeler tüm değeri değiştirir: eğer durumunuz bir nesne ise ve bunu çağırırsanız setState({ email: '...' }), diğer herhangi bir özellik (örneğin) password(Bunları manuel olarak birleştirmediğiniz sürece kaybolurlar.)
Bu farklılık, birden fazla temel durum değişkeninden tek bir nesneye yeniden düzenleme yaparken insanları yanıltıyor. Eğer değiştirirseniz const hem de const için const ve sonra genel bir şey yazın setForm({ : value })Bu durumda, yalnızca tek bir alana sahip bir durum nesnesi elde edersiniz. Çözüm, önceki nesneyi yaymaktır: setForm({ ...form, : value }).
Daha karmaşık uygulamalarda, genellikle çağrı yapmayacaksınız. setState (Ya da setSomething) her yerden doğrudan. Redux veya MobX gibi kütüphaneler kullanarak durumu merkezileştirebilir veya şunları kullanabilirsiniz: useReducer Bileşen düzeyindeki durum makineleri için kanca. Bu kurulumlarda, aynı değişmezlik ilkelerini uygulamaya devam edersiniz; tek fark, güncellemelerin nerede ve nasıl gerçekleştirildiğidir.
Yeniden oluşturma, performans ve useRef'in ne zaman kullanılacağı
React'te her durum güncellemesi, durumu yöneten bileşenin ve varsayılan olarak tüm alt bileşenlerinin yeniden oluşturulmasını tetikler. Bu, tasarım gereğidir: Yeniden oluşturma, kullanıcı arayüzünüzün mevcut verilerle senkronize kalmasını sağlar. Ancak bu aynı zamanda, özellikle alt bileşenler pahalı hesaplamalar yaptığında veya büyük listeler oluşturduğunda, düşüncesiz durum yerleşiminin gereksiz iş yüküne ve yavaş kullanıcı arayüzlerine neden olabileceği anlamına da gelir.
Bir giriş alanı ve uzun bir beceri listesi gösteren ayrı bir bileşen içeren bir uygulama hayal edin. Eğer üst bileşen hem kullanıcının yazdığı metne hem de listenin kendisine sahipse, her tuş vuruşu, beceri listesi değişmemiş olsa bile, tüm ağacı yeniden oluşturacaktır. Bu da boşa harcanan bir çabadır.
Bunu optimize etmenin basit bir yolu, alt bileşenleri bir sarmalayıcıya (wrapper) sarmaktır. React.memo. React.memo `<script>`, bir fonksiyon bileşeninin sonucunu önbelleğe alan daha üst düzey bir bileşendir: eğer özellikleri (props) render işlemleri arasında aynıysa, React yeniden render işlemini atlar. Dolayısıyla, beceri listesi bileşeniniz, `<script>` ile sarıldığında, React.memoHer tuş vuruşunda yeniden oluşturulmayacak; yalnızca belirli durumlarda yeniden oluşturulacak. skills Nesne gerçekten değişiyor (örneğin, yeni bir beceri eklediğinizde).
Tüm "devlet benzeri" veriler şuraya ait değildir: useState; ara sıra useRef daha iyi bir araçtır. MKS useRef Hook size değiştirilebilir bir nesne sunar. current Bileşenin ömrü boyunca kalıcı olan bir özellik, ancak güncellenmesi durumunda kaybolur. değil Yeniden oluşturmayı tetikler. Bu da zamanlayıcı kimlikleri, DOM öğesi referansları veya takip etmek istediğiniz ancak kullanıcı arayüzünde göstermenize gerek olmayan sayaçlar gibi şeyleri saklamak için mükemmeldir.
Basit bir örnek olarak, aşağıdaki şekilde uygulanan bir sayaç verilebilir. useRef yerine useState. Sayıyı saklarsanız countRef.current Ve bunu bir olay işleyicisinde artırırsanız, dahili değer değişir, ancak React yeniden render etmediği için görüntülenen JSX güncellenmez. Bu, önemli farkı göstermektedir: useState Kullanıcı arayüzünü yönlendiren değerler içindir; useRef Bu, görüntülemeyi etkilemeden korumak istediğiniz değerler içindir.
Değişmezlik ve doğrudan mutasyonun neden bir tuzak olduğu
React'in temel prensiplerinden biri, durum güncellemelerinin değiştirilemez olmasıdır. Bu, hiçbir şeyi asla değiştiremeyeceğiniz anlamına gelmez; mevcut değerleri (özellikle nesneleri ve dizileri) değiştirmek yerine, yenilerini oluşturup eskilerini kullanıcı arayüzünüzün tarihsel anlık görüntüleri olarak bırakmanız anlamına gelir.
Durumu doğrudan değiştirmek, zihinsel modeliniz ile React'in yaptığı şey arasındaki bağlantıyı koparır. Eğer şöyle bir şey yaparsanız... state.count++ Ya da doğrudan bir durum dizisine eklerseniz, React hiçbir şeyin değiştiğini bilmez çünkü güncelleme fonksiyonunu hiç çağırmadınız. React'in yeniden render etme zamanına karar vermek için kullandığı dahili anlık görüntü aynı kalırken, kodunuz değerin değiştiğini düşünür. İşte bu yüzden yeniden yüklediğinizde "kendiliğinden düzelen" hatalar ortaya çıkar.
Ayrıca, bir durum değerini başka bir değişkene atadıktan sonra o değişkeni değiştirmekten de kaçınmalısınız. Örneğin, yapmak const newCount = count; newCount++; Temel değerler için aynı altta yatan değeri değiştirmeye devam eder, nesneler için ise, const copy = stateObj; Bu işlem aslında bir kopya oluşturmaz; sadece aynı nesneye başka bir referans oluşturur. Doğru kopyalama, aşağıdaki gibi kalıplar gerektirir: { ...stateObj } nesneler için veya diziler için.
Redux, MobX (değiştirilemezlik için yapılandırıldığında) veya Immer gibi kütüphaneler, kısmen değiştirilemez kalıpları uygulamak veya basitleştirmek için mevcuttur. İster React'in yerleşik Hooks'larını ister bir durum yönetimi kütüphanesini kullanın, altın kural geçerlidir: React'in değişikliği algılayıp yeniden render etmesini bekliyorsanız, mevcut durumu asla yerinde değiştirmeyin.
Asenkron güncellemeler, gruplandırma ve eski durum
React state ile ilgili incelikli ama çok önemli bir ayrıntı, güncellemelerin eşzamansız ve planlı bir şekilde yapılması, hemen uygulanmamasıdır. Aradığın zaman setState veya bir kanca tutucu gibi setCountReact, gelecekteki bir zaman dilimi için yeniden oluşturma işlemini "sıraya alır". Bu, kodunuzun hemen güncellenip yeniden oluşturulmasını engellemez; bu da React'in birden fazla güncellemeyi gruplandırmasına ve performansı sorunsuz tutmasına olanak tanır.
Bu zamanlama modeli, aynı senkron blok içinde güncelleyiciyi çağırdıktan hemen sonra durumu okumaya güvenemeyeceğiniz anlamına gelir. Genellikle elde edeceğiniz değer eski anlık görüntü olacaktır. Bunun yerine, güncelleyiciyi bir istek olarak düşünmelisiniz: "Bir sonraki render işleminde bu değeri (veya bu dönüşüm fonksiyonunu) kullanın".
Bu, özellikle kapanışlar içinden mevcut değerine göre durumu güncellediğinizde önemlidir. setTimeout veya abonelik geri bildirimleri. Bu geri çağırma işlevleri, oluşturuldukları anda mevcut olan durumu yakalar. Eğer daha sonra şunu yaparsanız... setCount(count + 1) Mola sırasında, count Bahsettiğiniz veri, geri çağırma işlevi gerçekten çalışana kadar güncelliğini yitirmiş olabilir.
Bu olgu "durgunluk hali" veya "durgun kapanmalar" olarak bilinir. Örneğin, tıklandığında bir zaman aşımı ayarlayan ve ardından bir saniye sonra durumu artıran bir işlevi çağıran bir düğmeniz varsa, art arda yapılan hızlı tıklamalar durumu doğru şekilde artırmayabilir. Her zaman aşımı geri çağırma işlevi eski değeri kullanır. count Zaman aşımının ne zaman planlandığını kaydetti.
En sağlam çözüm, durum ayarlayıcınızın işlevsel güncelleme biçimini kullanmaktır. Yerine setCount(count + 1) Zaman aşımı süresi içinde yazıyorsunuz. setCount(prevCount => prevCount + 1)Artık her geri çağırma işlevi, güncelleme uygulandığı anda geçerli olan en son önceki değeri alır; zaman aşımı oluşturulduğunda kapsamda olan değeri değil. Bu, kapanışlarınızın davranışını değiştirmeden eski durum sorununu ortadan kaldırır.
React'in dokümantasyonu ayrıca daha az bilinen bir ayrıntıya da dikkat çekiyor: eğer fonksiyonel güncellemeniz hiçbir şey döndürmüyorsa (undefinedBu durumda React yeniden render işlemini atlayacaktır. Bu, güncelleme işlevlerinizin, açıkça bir güncellemeyi engellemek istemediğiniz sürece (ki bu standart yöntemlerle nadiren arzu edilen bir durumdur), her zaman bir sonraki durum değerini döndürmesi (veya önceki değeri yeniden kullanması) gerektiği anlamına gelir. useState kullanımı.
Asenkron zamanlama, gruplandırma ve kapatma davranışının bu kombinasyonunu anlamak, zaman aşımı, aralıklar, abonelikler veya hızlı kullanıcı etkileşimleriyle ilgilenen uygulamalarda güvenilir durum mantığı yazmak için kritik öneme sahiptir. Durum belirleyicilerin güncellemeleri anında gerçekleştirmek yerine zamanladığını içselleştirdiğinizde, eskiden rastgele gibi görünen hatalar anlam kazanmaya başlayacaktır.
Tüm bu fikirleri bir araya getirdiğinizde—props vs state, sınıf yaşam döngüleri vs Hooks, değişmezlik, kontrollü bileşenler, useRef Görsel olmayan değerler, memoizasyon, eşzamansız güncellemeler ve eski kapanışlar için; sonuç olarak React kullanıcı arayüzlerinin zaman içinde nasıl geliştiğine dair güçlü ve öngörülebilir bir model elde edersiniz. Zorunlu DOM değişiklikleri yerine, net durum modelleri tasarlarsınız ve yeniden oluşturma işlemini React'e bırakırsınız; bu da uygulamanız büyüdükçe bileşenlerinizi anlamayı, test etmeyi ve genişletmeyi kolaylaştırır.

