React’te Olay İşleyici İşlevlerini Oluşturmak için 5 Kritik İpucu – JSManifest

React'te Olay İşleyici İşlevlerini Oluşturmak için 5 Kritik İpucu – JSManifest

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 .concatimza ş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>
  )
}

imza-değişiklik-olay-işleyici-javascript-tepki

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:

olay-işleyici-eşzamansız-durumlar

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:

javascript-yürütme-bağlam-diyagramı-akış şeması

Bu, örneklerimizdeki tepkinin oluşturma aşamasıdır (Bunu, tepkilerine sahip olmak olarak düşünebilirsiniz. kendi yürütme bağlamı):

tepki-render-aşama-uzlaşma-akış şeması

Bununla birlikte, çağrımıza bir göz atalım setCollapsed Yeniden:

oluşturma-durum-aşaması-tepki-güncelleme

güncelleme-oluşturma-aşaması-tepki2

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:

tepki-durum-güncelleme-uzlaşma2

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.