
JavaScript, benzersiz işlev oluşturma ve oluşturma yöntemleriyle övülür. Bunun nedeni JavaScript’te işlevlerin birinci sınıf vatandaşlar yani değer olarak ele alınabilirler ve diğerlerinin bir değişkene atanmak, bir işlev argümanı olarak iletilmek, bir işlevden döndürülmek, vb. gibi sahip olduğu tüm operasyonel özelliklere sahip olabilirler.
Tepki halinde olay işleyicileri oluşturmak için 5 kritik ipucu üzerinde olacağız. Bu gönderi mümkün olan her şeyi kapsamayacak, ancak her tepki geliştiricisinin bilmesi gereken olay işleyicileri oluşturmanın önemli yollarını kapsayacak. minimal olarak!
Bir girdi öğesiyle başlayacağız ve bir value
ve onChange
başlamak için pervane:
import React from 'react'
import './styles.css'
function MyInput() {
const [value, setValue] = React.useState('')
function onChange(e) {
setValue(e.target.value)
}
return (
<div>
<input type="text" value={value} onChange={onChange} />
</div>
)
}
export default MyInput
Bizim olay işleyicisi bu onChange
ve ilk argüman, işleyicinin eklendiği öğeden gelen olay nesnesidir.
Buradan neyi geliştirebiliriz? Yeniden kullanılabilir bileşenler yazmak genellikle iyi bir uygulamadır ve biz Yapabilmek bunu tekrar kullanılabilir hale getirin.
1. Ayarlayıcıyı daha yüksek bir seviyeye taşıyın
Bir yol, durumu belirleme sorumluluğunu devretmek. value
kadar devlet props
diğer bileşenlerin bu girişi yeniden kullanabilmesi için:
import React from 'react'
import MyInput from './MyInput'
function App() {
const [value, setValue] = React.useState('')
return <MyInput value={value} />
}
export default App
Bu, ebeveyne (durum ayarlayıcıyı tutan) olay işleyicisi üzerinde kontrol vermemiz gerektiği anlamına gelir:
function App() {
const [value, setValue] = React.useState('')
function onChange(e) {
setValue(e.target.value)
}
return <MyInput value={value} onChange={onChange} />
}
function MyInput({ value, onChange }) {
return (
<div>
<input type="text" value={value} onChange={onChange} />
</div>
)
}
Ancak tüm yaptığımız, durumu ve olay işleyiciyi üst öğeye ve nihayetinde App
bileşen bizimkiyle tamamen aynı MyInput
, yalnızca farklı şekilde adlandırılmıştır. Ne anlamı var?
2. Genişletilebilirlik amacıyla daha fazla bilgiye ihtiyaç duyulabiliyorsa, olay işleyicilerinizi sarın
Beste yapmaya başladığımızda işler değişmeye başlar. şuna bir göz atın MyInput
bileşen. doğrudan atamak yerine onChange
onun için input
yerine bu yeniden kullanılabilir bileşene onu daha kullanışlı hale getiren bazı ek işlevler verebiliriz.
manipüle edebiliriz onChange
ile onu başka bir onChange içinde oluşturmak ve yenisini ekleyin onChange
bunun yerine öğenin üzerine. yeni içinde onChange
orijinali arayacak onChange
böylece işlevsellik hala normal şekilde davranabilir – hiçbir şey değişmemiş gibi.
İşte bir örnek:
function MyInput({ value, onChange: onChangeProp }) {
function onChange(e) {
onChangeProp(e)
}
return (
<div>
<input type="text" value={value} onChange={onChange} />
</div>
)
}
Bu, gerektiğinde ek mantık enjekte etmek için harika bir yetenek getiriyor. value
arasında input
değişir. Normal davranıyor çünkü hala orijinali çağırıyor onChange
bloğunun içinde.
Örneğin, şimdi yapabiliriz Kuvvet giriş öğesi yalnızca sayı değerlerini kabul eder ve yalnızca maksimum 6 karakter uzunluğunda olur; bu, kullanıcının telefonları aracılığıyla oturum açma işlemlerini doğrulamak için bunu kullanmak istiyorsak yararlıdır:
function isDigits(value) {
return /^d+$/.test(value)
}
function isWithin6(value) {
return value.length <= 6
}
function MyInput({ value, onChange: onChangeProp }) {
function onChange(e) {
if (isDigits(e.target.value) && isWithin6(e.target.value)) {
onChangeProp(e)
}
}
return (
<div>
<input type="text" value={value} onChange={onChange} />
</div>
)
}
Gerçekte olsa da, bunların hepsi hala ebeveynde uygulanabilirdi. App
şimdiye kadar herhangi bir sorun olmadan. Ama ya onChange
ebeveyn ihtiyaçları işleyicisi daha fazla sadece Etkinlik nesneden MyInput
? bu onChange
oradaki işleyici artık işe yaramaz:
function App() {
const [value, setValue] = React.useState('')
function onChange(e) {
setValue(e.target.value)
}
return <MyInput value={value} onChange={onChange} />
}
Ama ne olabilir App
muhtemelen olay nesnesinden başka bir şeye ihtiyaç duymak ve öğenin bir değerinin değiştiğini bilmek, bu nedenle zaten farkında olduğu için yürütme bağlamı içindedir. onChange
işleyici?
3. Argümanlar aracılığıyla oluşturulmuş orijinal işleyiciden yararlanın
Doğrudan erişime sahip olmak input
elemanın kendisi son derece yardımcı olabilir. Bu, bazılarına sahip olmanın yararlı olduğu anlamına gelir ref
nesne, olay nesnesiyle birlikte geçti. beri kolayca yapılır onChange
işleyici burada oluşturuldu:
function MyInput({ value, onChange: onChangeProp }) {
function onChange(e) {
if (isDigits(e.target.value) && isWithin6(e.target.value)) {
onChangeProp(e)
}
}
return (
<div>
<input type="text" value={value} onChange={onChange} />
</div>
)
}
Tek yapmamız gereken tepki kancasını ilan etmek useRef
şuna takın input
ve onu bir nesnenin içinde ikinci parametre onChangeProp
böylece arayan ona erişebilir:
function MyInput({ value, onChange: onChangeProp }) {
const ref = React.useRef()
function onChange(e) {
if (isDigits(e.target.value) && isWithin6(e.target.value)) {
onChangeProp(e, { ref: ref.current })
}
}
return (
<div>
<input ref={ref} type="text" value={value} onChange={onChange} />
</div>
)
}
function App() {
const [value, setValue] = React.useState('')
function onChange(e, { ref }) {
setValue(e.target.value)
if (ref.type === 'file') {
} else if (ref.type === 'text') {
}
}
return (
<div>
<MyInput value={value} onChange={onChange} />
</div>
)
}
4. Üst düzey işlev işleyicisinin imzasını ve oluşturulan işleyiciyi aynı tutun
Bu genellikle bir çok Oluşturulan işlevlerin imzasını orijinaliyle aynı tutmak için önemli bir uygulama. Demek istediğim, burada örneklerimizde her ikisinin de ilk parametresi onChange
işleyiciler olay nesnesi için ayrılmıştır.
İşlevleri bir araya getirirken imzayı aynı tutmak, gereksiz hataların ve karışıklığın önlenmesine yardımcı olur.
Parametrelerin konumlarını şöyle değiştirmiş olsaydık:
O zaman bileşeni yeniden kullandığımızda bunu unutmak ve karıştırmak kolaydır:
function App() {
const [value, setValue] = React.useState('')
function onChange(e, { ref }) {
setValue(e.target.value)
}
return (
<div>
<MyInput value={value} onChange={onChange} />
</div>
)
}
Ayrıca, bu karışıklığı önlediğimizde siz ve diğer geliştiriciler için daha az stresli oluyor.
Uygulamanın normal şekilde davranmasını sağlarken arayanın istediği kadar olay işleyici sağlamasına izin vermek buna iyi bir örnektir:
const callAll = (...fns) => (arg) => fns.forEach((fn) => fn && fn(arg))
function MyInput({ value, onChange, onChange2, onChange3 }) {
return (
<input
type="text"
value={value}
onChange={callAll(onChange, onChange2, onChang3)}
/>
)
}
En az biri aşağıdaki gibi dizelere özgü bir yöntem yapmaya çalıştıysa .concat
imza şu olduğundan bir hata oluşur function(event, ...args)
ve yok function(str, ...args)
:
function App() {
const [value, setValue] = React.useState('')
function onChange(e, { ref }) {
console.log(`current state value: ${value}`)
console.log(`incoming value: ${e.target.value}`)
setValue(e.target.value)
console.log(`current state value now: ${value}`)
}
function onChange2(e) {
e.concat(['abc', {}, 500])
}
function onChange3(e) {
console.log(e.target.value)
}
return (
<div>
<MyInput
value={value}
onChange={onChange}
onChange2={onChange2}
onChange3={onChange3}
/>
</div>
)
}
5. Olay işleyicileri içinde referans vermekten ve duruma bağlı olmaktan kaçının (Kapanışlar)
Bu gerçekten tehlikeli bir şey!
Doğru yapılırsa, geri arama işleyicilerinde durumla ilgili herhangi bir sorun yaşamamalısınız. Ancak bir noktada hata yaparsanız ve bu, hata ayıklaması zor olan sessiz hatalara yol açarsa, o zaman sonuçlar, gününüzün geri almak istediğiniz o fazladan zamanını yutmaya başlar.
Böyle bir şey yapıyorsanız:
function onChange(e, { ref }) {
console.log(`current state value: ${value}`)
console.log(`incoming value: ${e.target.value}`)
setValue(e.target.value)
console.log(`current state value now: ${value}`)
}
Muhtemelen bu işleyicileri tekrar ziyaret etmeli ve beklediğiniz doğru sonuçları alıp almadığınızı kontrol etmelisiniz.
Eğer bizim input
değeri var "23"
ve başka bir tane yazıyoruz "3"
klavyede, sonuçlar şöyle diyor:
JavaScript’teki yürütme bağlamını anlarsanız, bunun bir anlamı yoktur, çünkü setValue
sonraki satıra geçmeden önce yürütmeyi çoktan bitirmişti!
Eh, bu aslında hala doğru. JavaScript’in şu anda yanlış yaptığı hiçbir şey yok. Aslında tepki işini yapıyor.
Oluşturma sürecinin tam bir açıklaması için onların sayfasına gidebilirsiniz. belgeler.
Ama kısacası, temelde her tepki anında yeni bir işlemek bir aşama alır “enstantane fotoğraf” mevcut olan her şeyin bu işleme aşamasına özel. Reaksiyonun esas olarak ağacı temsil eden bir reaksiyon elementleri ağacı oluşturduğu bir aşamadır. o sırada.
Tanım olarak çağrı setValue
yapmak yeniden oluşturma işlemine neden olur, ancak bu oluşturma aşaması zamanın gelecekteki bir noktasındadır! Bu yüzden devlet value
hala 23
sonra setValue
yürütmeyi bitirmişti çünkü yürütme o sırada o render için özeldiriçinde yaşadıkları kendi küçük dünyalarına sahip olmak gibi.
JavaScript’te yürütme bağlamı kavramı şöyle görünür:
Bu, örneklerimizdeki tepkinin oluşturma aşamasıdır (Bunu, tepkilerine sahip olmak olarak düşünebilirsiniz. kendi yürütme bağlamı):
Bununla birlikte, çağrımıza bir göz atalım setCollapsed
Yeniden:
Bunların hepsi aynı oluşturma aşamasında oluyor, bu yüzden çökmüş hala true
ve person
olarak geçiliyor null
. Bileşenin tamamı yeniden oluşturulduğunda, sonraki oluşturma aşamasındaki değerler, öncekinden gelen değerleri temsil edecektir: