SetState'in işlevsel sözdiziminin işlevsel bileşenlere tepki vermede kullanımı nedir? [çiftleme]
sahip olan fonksiyonel bileşenlerden bahsediyoruz useState
diyelimki
const [age, setAge] = useState(0)
şimdi güncelleme sırasında öncekini age
kullanmam gerektiğini söyleyelimage
React belgeleri , bir işlevi iletebileceğiniz FONKSİYONEL GÜNCELLEMELER adı verilen bir şeyden bahseder ve bunun argümanı, durumun önceki değeri olacaktır, örn.
setState((previousAge) => previousAge + 1)
Sadece yapabildiğimde neden bunu yapmam gerekiyor?
setState(previousAge + 1)
işlevsel kullanmanın faydaları nelerdir setState
,
Sınıf tabanlı bileşenlerde işlevsel olarak durum güncellemelerinin gruplanması denen bir şey olduğunu biliyorum , ancak işlevsel bileşen belgelerinde buna benzer bir şey bulamıyorum.
Yanıtlar
Aynı değildirler, güncellemeniz eyalette bulunan önceki bir değere bağlıysa, o zaman işlevsel formu kullanmalısınız. Bu durumda işlevsel formu kullanmazsanız, kodunuz bazen kırılır.
Neden ve ne zaman kırılıyor
React fonksiyonel bileşenleri sadece kapanışlardır, kapanışta sahip olduğunuz durum değeri güncelliğini yitirmiş olabilir - bu, kapanış içindeki değerin o bileşen için React durumundaki değerle eşleşmediği anlamına gelir, bu, aşağıdaki durumlar:
1- eşzamansız işlemler ( Bu örnekte yavaş ekle'ye tıklayın ve ardından ekle düğmesine birden çok kez tıklayın, daha sonra yavaş ekle düğmesi tıklandığında durumun kapanmanın içindekine sıfırlandığını göreceksiniz)
const App = () => {
const [counter, setCounter] = useState(0);
return (
<>
<p>counter {counter} </p>
<button
onClick={() => {
setCounter(counter + 1);
}}
>
immediately add
</button>
<button
onClick={() => {
setTimeout(() => setCounter(counter + 1), 1000);
}}
>
Add
</button>
</>
);
};
2- Güncelleme işlevini aynı kapanışta birden çok kez çağırdığınızda
const App = () => {
const [counter, setCounter] = useState(0);
return (
<>
<p>counter {counter} </p>
<button
onClick={() => {
setCounter(counter + 1);
setCounter(counter + 1);
}}
>
Add twice
</button>
</>
);
}
Ayarlayıcınızın ne kadar hızlı / sıklıkla arandığına bağlı olarak sorunlar ortaya çıkabilir.
Kapanıştan değeri alarak basit yolu kullanıyorsanız, iki render arasındaki sonraki çağrılar istenen etkiyi yaratmayabilir.
Basit bir örnek:
function App() {
const [counter, setCounter] = useState(0);
const incWithClosure = () => {
setCounter(counter + 1);
};
const incWithUpdate = () => {
setCounter(oldCounter => oldCounter + 1);
};
return (<>
<button onClick={_ => { incWithClosure(); incWithClosure(); }}>
Increment twice using incWithClosure
</button>
<button onClick={_ => { incWithUpdate(); incWithUpdate(); }}>
Increment twice using incWithUpdate
</button>
<p>{counter}</p>
</>);
}
Her iki düğme de artırma yöntemlerinden birini iki kez çağırır. Ancak şunu gözlemliyoruz:
- İlk düğme, sayacı yalnızca 1 artıracaktır
- İkinci düğme, sayacı 2 artıracaktır, bu muhtemelen istenen sonuçtur.
Bu ne zaman olabilir?
- Açıkçası, eğer
incWithClosure
birbiri ardına birden çok kez çağrılırsa - Eşzamansız görevler söz konusuysa, bu kolayca gerçekleşebilir (aşağıya bakın)
- Belki de React'in yapacak çok işi varsa, zamanlama algoritmaları aynı olay işleyicisini kullanarak çok sayıda çok hızlı tıklamayı işlemeye karar verebilir.
Eşzamansız çalışma örneği (bir kaynağın yüklenmesini simüle ederek):
function App() {
const [counter, setCounter] = useState(0);
const incWithClosureDelayed = () => {
setTimeout(() => {
setCounter(counter + 1);
}, 1000);
};
const incWithUpdateDelayed = () => {
setTimeout(() => {
setCounter((oldCounter) => oldCounter + 1);
}, 1000);
};
return (
<>
<button onClick={(_) => incWithClosureDelayed()}>
Increment slowly using incWithClosure
</button>
<button onClick={(_) => incWithUpdateDelayed()}>
Increment slowly using incWithUpdate
</button>
<p>{counter}</p>
</>
);
}
İlk düğmeye iki kez tıklayın (bir saniye içinde) ve sayacın yalnızca 1 arttığını gözlemleyin. İkinci düğme doğru davranışa sahiptir.
Eğer yoksa Çünkü olacaktır sizin için eski bir değeri elde noktada bulmak age
. Sorun şu ki, bazen önerdiğiniz şey işe yarayacak. Ama bazen olmayacak. Bugün mevcut kodunuzda kırılmayabilir, ancak birkaç hafta önce yazdığınız farklı bir kodda veya şu andaki kodunuzda birkaç ay sonra kırılabilir.
Belirti gerçekten çok tuhaf. Bir jsx bileşeninin içindeki değişkenin değerini {x}
sözdizimini kullanarak yazdırabilir ve daha console.log
sonra jsx bileşenini oluşturduktan sonra (daha önce değil) kullanarak aynı değişkeni yazdırabilir ve console.log
değerin eski olduğunu görebilirsiniz - işlemeden console.log
sonra gerçekleşen şey bir şekilde daha eski değere sahip olabilir renderdan daha fazla.
Dolayısıyla, durum değişkenlerinin gerçek değeri normal kodda her zaman doğru çalışmayabilir - bunlar yalnızca bir işlemedeki en son değeri döndürmek için tasarlanmıştır. Bu nedenle, bir durum ayarlayıcısındaki geri çağrı mekanizması, bir render dışında normal koddaki bir durum değişkeninin en son değerini almanıza izin vermek için uygulandı.