React Uygulamaları Oluştururken Yapılmaması Gereken 10 Şey – JSManifest

React Uygulamaları Oluştururken Yapılmaması Gereken 10 Şey – JSManifest

Tepki web’de geliştirme yapmak için çok popüler bir araç ve eminim ki hayranlar böyle harika bir kütüphaneyle ellerinizi kirletebildiğiniz için kutsanmış hissediyorsunuzdur 🙂

Ne yazık ki hayatta hiçbir şey mükemmel değildir ve tepki de farklı değildir.

React kendi setiyle birlikte gelir. yakalanmış–Bazıları, onlarla ilgilenmezseniz, potansiyel olarak uygulamalarınız için ciddi bir sorun haline gelebilir şimdi.

İşte React Uygulamaları Oluştururken Yapılmaması Gereken ___ Şeyler:

1. Kendi Özel Dünyanızda Çok Fazla Zaman Harcamak

Projenizdeki her şeyi kodlamak için çok fazla zaman harcıyorsanız ve toplulukta neler olup bittiğini okumak için biraz zaman ayırmıyorsanız, Might risk altında olmak toplulukta bildirilen kötü uygulamaları kodlamak. Ve nihayet orta boy bir gönderide bunun olduğunu öğrenme şansını elde edene kadar 20 kez yapana kadar bu kötü uygulamaları kodlamaya devam etme riski altında olabilirsiniz. kötü.

Bu ne zaman oldu, şimdi Geri dönüp bu 20 kod uygulamasını yeniden gözden geçirmeniz gerekiyor çünkü herkes sizden öndeyken çok geç fark ettiniz ve daha yeni haberlere geçtiniz.

Reaksiyon serbest bırakıldığında kancalar, çok heyecanlandım ve herkesin heyecanlandığı bu yeni oyuncaklarla oynamak için bir dizi mini proje yapmaya başladım. Kancaların istikrarlı olacağına dair birkaç kaynak okuduktan sonra, bunları projelerimde daha ciddi bir şekilde uygulamaya başladım. kullanıyordum Kullanım Durumu ve kullanım Etkisi patron gibi her yerde.

Ve sonra bağlantı kuran biriyle karşılaştım bu twitter tweetibu da beni useReducer hakkında biraz daha araştırma yapmaya yönlendirdi.

O 30 dakikalık araştırma geri dönüp iyi miktarda kodu yeniden düzenlemem için yeterliydi.

2. kullanma .bağlamak (Sınıf bileşeni kurucuları değil)

Bence çoğumuz tepki veren geliştiriciler, .bağlamak referans vermek istiyorsak sınıf yöntemlerimiz Bu yöntemlerinde kendi sınıf örneklerine erişmek için. (Bir aktarıcı sınıf özelliklerinizi ve yöntemlerinizi aktarmak için.

Bu harika ve onları ilan etmeyi tercih etmeyi kabul ediyorum. ok fonksiyonları.

Ama bahsedeceğim bu kısım bununla ilgili değil. Hakkında satır içi işlevler–veya içinde tanımlanan işlevler işleme yöntemi tepki bileşeninin bir parçası ve bir alt bileşene destek olarak aktarıldı.

Oluşturma yönteminde satır içi işlevler tanımlandığında, bileşen her yeniden oluşturulduğunda tepki yeni bir işlev örneği atamaya başlar. Bunun performans sorunlarına neden olduğu bilinmektedir. savurgan yeniden oluşturma.

Şu örneğe bir göz atalım:

const ShowMeTheMoney = () => {
  const [money, setMoney] = useState(0)

  const showThemTheMoney = (money) => {
    setMoney(money)
  }

  const hideTheMoney = () => {
    setMoney(null)
  }

  const sayWhereTheMoneyIs = (msg) => {
    console.log(msg)
  }

  return (
    <div>
      <h4>Where is the money?</h4>
      <hr />
      <div style={{ display: 'flex', alignItems: 'center' }}>
        <SomeCustomButton
          type="button"
          onClick={() => sayWhereTheMoneyIs("I don't know")}
        >
          I'll tell you
        </SomeCustomButton>{' '}
        <SomeCustomButton type="button" onClick={() => showThemTheMoney(0.05)}>
          I'll show you
        </SomeCustomButton>
      </div>
    </div>
  )
}

Biz bilmek o onClick={() => sayWhereTheMoneyIs("I don't know")} ve onClick={() => showThemTheMoney(0.05)} vardır satır içi işlevler.

Birkaç öğretici gördüm (biri dahil Udemy) bunu yapmaya teşvik eden:

return (
  <div>
    <h4>Where is the money?</h4>
    <hr />
    <div style={{ display: 'flex', alignItems: 'center' }}>
      <SomeCustomButton
        type="button"
        onClick={sayWhereTheMoneyIs.bind(null, "I don't know")}
      >
        I'll tell you
      </SomeCustomButton>{' '}
      <SomeCustomButton
        type="button"
        onClick={showThemTheMoney.bind(null, 0.05)}
      >
        I'll show you
      </SomeCustomButton>
    </div>
  </div>
)

Bu öyle gibi referansı önbelleğe aldığı gibi, böylece gereksiz yeniden oluşturmalardan kaçınırlar çünkü render yönteminde ok satır içi işlevlerini kullanmıyorama onlar aslında hala yeni işlevler oluşturma her render aşamasında!

Bazılarımız, sınıf bileşenlerinin trend olduğu zamanlarda tepki ekosistemindeki topluluğu takip ediyor olsaydık, bunu zaten biliyor olabiliriz.

Bununla birlikte, tepki kancaları serbest bırakıldığından beri, .bind hakkındaki konuşmalar, sınıf bileşenleri daha az popüler hale geldiğinden ve genellikle, .bağlamak konuşulacak konuydu, genellikle olmak bağlama sınıfı yöntemleri hakkında. Ve buna ek olarak, yukarıdaki bu örnekler, sınıf yöntemlerine hiçbir şekilde bağlayıcı değildir, bu nedenle, yeterince dikkatli değilseniz, buradaki sonuçları fark etmeyi daha da zorlaştırır.

bu yeni gelenler özellikle bu anti-desen farkında olmalı!

3. Çocuklara Anahtar Olarak Dinamik Değerler Aktarma

sen hiç öyle bir zamana denk geldin mi keçe eşlenen çocuklara benzersiz anahtarlar sağlamak zorunda kaldınız mı?

Benzersiz anahtarlar sağlamak iyidir:

const Cereal = ({ items, ...otherProps }) => {
  const indexHalf = Math.floor(items.length / 2)
  const items1 = items.slice(0, indexHalf)
  const items2 = items.slice(indexHalf)
  return (
    <>
      <ul>
        {items1.map(({ to, label }) => (
          <li key={to}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
      <ul>
        {items2.map(({ to, label }) => (
          <li key={to}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
    </>
  )
}

Şimdi farz edin ki bazı ile değerler öğeler1 bazılarıyla aynı olur öğeler2.

Bazı insanlar buna benzer bir bileşeni yeniden düzenlemek istediğinde, sonunda şöyle bir şey yapacaklarını gördüm:

import { generateRandomUniqueKey } from 'utils/generating'

const Cereal = ({ items, ...otherProps }) => {
  const indexHalf = Math.floor(items.length / 2)
  const items1 = items.slice(0, indexHalf)
  const items2 = items.slice(indexHalf)
  return (
    <>
      <ul>
        {items1.map(({ to, label }) => (
          <li key={generateRandomUniqueKey()}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
      <ul>
        {items2.map(({ to, label }) => (
          <li key={generateRandomUniqueKey()}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
    </>
  )
}

Bu yapmak Her çocuğa benzersiz anahtarlar sağlayarak işi bitirin. Ama yanlış olan iki şey var:

  1. Benzersiz değerler üreterek sadece gereksiz işler yapmakla kalmıyoruz, aynı zamanda anahtar her seferinde farklı olduğu için her işlemede tüm düğümlerimizi yeniden oluşturmak.

  2. bu anahtar tepki kavramı kimlik hakkında her şey. Ve hangi bileşenin hangisi olduğunu belirlemek için, anahtarlar yapmak benzersiz olmalı, ancak böyle değil.

Bunun gibi bir şey biraz daha iyi olabilirdi:

import { generateRandomUniqueKey } from 'utils/generating'

const Cereal = ({ items, ...otherProps }) => {
  const indexHalf = Math.floor(items.length / 2)
  const items1 = items.slice(0, indexHalf)
  const items2 = items.slice(indexHalf)
  return (
    <>
      <ul>
        {items1.map(({ to, label }) => (
          <li key={`items1_${to}`}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
      <ul>
        {items2.map(({ to, label }) => (
          <li key={`items2_${to}`}>
            <Link to={to}>{label}</Link>
          </li>
        ))}
      </ul>
    </>
  )
}

Şimdi, her öğenin kendi benzersiz anahtar değerine sahip olacağından emin olmalıyız. korumak onların kimliği.

4. Varsayılan Parametreleri Null Üzerinden Bildirme

Bir zamanlar buna benzer bir hata ayıklamak için çok zaman harcamaktan suçluydum:

const SomeComponent = ({ items = [], todaysDate, tomorrowsDate }) => {
  const [someState, setSomeState] = useState(null)

  return (
    <div>
      <h2>Today is {todaysDate}</h2>
      <small>And tomorrow is {tomorrowsDate}</small>
      <hr />
      {items.map((item, index) => (
        <span key={`item_${index}`}>{item.email}</span>
      ))}
    </div>
  )
}

const App = ({ dates, ...otherProps }) => {
  let items
  if (dates) {
    items = dates ? dates.map((d) => new Date(d).toLocaleDateString()) : null
  }

  return (
    <div>
      <SomeComponent {...otherProps} items={items} />
    </div>
  )
}

bizim içinde Uygulama bileşen, eğer tarih olmak biter yalancıile başlatılacak hükümsüz.

Ve eğer kodu çalıştırırsak – eğer benim gibiyseniz, içgüdülerimiz bize şunu söyler: öğeler falsey değeriyse varsayılan olarak boş bir diziye başlatılmalıdır. Ancak uygulamamız ne zaman çökecek? tarih yanlış çünkü öğeler boş. Ne?

Varsayılan işlev parametreleri, aşağıdaki durumlarda adlandırılmış parametrelerin varsayılan değerlerle başlatılmasına izin verir: değer yok veya tanımsız geçti!

Bizim durumumuzda, her ne kadar hükümsüz falsey, hala bir değer!

Bu hata, özellikle hükümsüz değer redux redüktörlerinden geliyordu! Ah.

5. Tekrarlanan Kodlara Dokunulmadan Bırakmak

Bazen en hızlı çözüm olabileceğinden, bir düzeltmeyi zorlamak için aceleye geldiğinizde kodu kopyalayıp yapıştırmak cazip gelebilir.

İşte yinelenen koda bir örnek:

const SomeComponent = () => (
  <Body noBottom>
    <Header center>Title</Header>
    <Divider />
    <Background grey>
      <Section height={500}>
        <Grid spacing={16} container>
          <Grid xs={12} sm={6} item>
            <div className={classes.groupsHeader}>
              <Header center>Groups</Header>
            </div>
          </Grid>
          <Grid xs={12} sm={6} item>
            <div>
              <img src={photos.groups} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    </Background>
    <Background grey>
      <Section height={500}>
        <Grid spacing={16} container>
          <Grid xs={12} sm={6} item>
            <div className={classes.labsHeader}>
              <Header center>Labs</Header>
            </div>
          </Grid>
          <Grid xs={12} sm={6} item>
            <div>
              <img src={photos.labs} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    </Background>
    <Background grey>
      <Section height={300}>
        <Grid spacing={16} container>
          <Grid xs={12} sm={6} item>
            <div className={classes.partnersHeader}>
              <Header center>Partners</Header>
            </div>
          </Grid>
          <Grid xs={12} sm={6} item>
            <div>
              <img src={photos.partners} alt="" className={classes.img} />
            </div>
          </Grid>
        </Grid>
      </Section>
    </Background>
  </Body>
)

Şimdi, bu bileşenlerin birden çok kez yeniden kullanılabilecekleri şekilde nasıl soyutlanacağını düşünmeye başlamanın tam zamanı. uygulamayı değiştirmeden. Birinde bir stil sorunu varsa Kafes bileşenleri çevrelerine göre ızgara kapsayıcıs, her birini manuel olarak değiştirmeniz gerekir.

Bunu kodlamanın daha iyi bir yolu, muhtemelen tekrarlanan kısımları soyutlamak ve biraz farklı olan sahne malzemelerini aktarmaktır:

const SectionContainer = ({
  bgProps,
  height = 500,
  header,
  headerProps,
  imgProps,
}) => (
  <Background {...bgProps}>
    <Section height={height}>
      <Grid spacing={16} container>
        <Grid xs={12} sm={6} item>
          <div {...headerProps}>
            <Header center>{header}</Header>
          </div>
        </Grid>
        <Grid xs={12} sm={6} item>
          <div>
            <img {...imgProps} />
          </div>
        </Grid>
      </Grid>
    </Section>
  </Background>
)

const SomeComponent = () => (
  <Body noBottom>
    <Header center>Title</Header>
    <Divider />
    <SectionContainer
      header="Groups"
      headerProps={{ className: classes.groupsHeader }}
      imgProps={{ src: photos.groups, className: classes.img }}
    />
    <SectionContainer
      bgProps={{ grey: true }}
      header="Labs"
      headerProps={{ className: classes.labsHeader }}
      imgProps={{ src: photos.labs, className: classes.img }}
    />
    <SectionContainer
      height={300}
      header="Partners"
      headerProps={{ className: classes.partnersHeader }}
      imgProps={{ src: photos.partners, className: classes.img }}
    />
  </Body>
)

Şimdi patronunuz fikrini değiştirirse ve tüm bu bölümleri 300 piksel yükseklikte, sadece sahipsin bir değiştireceğiniz yer.

Şimdi, birkaç kullanım durumunu destekleyen bir bileşen yapmak istiyorsak, böyle bir çözüm önermeye çalışmıyorum, bu, belirli kullanımlar içindir. bilmek yeniden kullanılacak sadece o ortam. için daha dinamik, yeniden kullanılabilir bir çözüm BölümKonteyner çoklu kullanım durumlarını destekleyen, muhtemelen bunun gibi daha genel olacak şekilde kodlanmış olurdu, hala onsuz uygulamanın değiştirilmesi:

const SectionContainer = ({
  bgProps,
  sectionProps,
  children,
  gridContainerProps,
  gridColumnLeftProps,
  gridColumnRightProps,
  columnLeft,
  columnRight,
}) => (
  <Background {...bgProps}>
    <Section {...sectionProps}>
      {children || (
        <Grid spacing={16} container {...gridContainerProps}>
          <Grid xs={12} sm={6} item {...gridColumnLeftProps}>
            {columnLeft}
          </Grid>
          <Grid xs={12} sm={6} item {...gridColumnRightProps}>
            {columnRight}
          </Grid>
        </Grid>
      )}
    </Section>
  </Background>
)

Bu şekilde, geliştiricinin, temeldeki uygulamayı korurken isteğe bağlı olarak bileşenlerin herhangi bir bölümünü gerektiği gibi genişletmesine izin veriyoruz.

6. Yapıcıda Props’ı Başlatma

Yapıcıda durumu başlattığınızda:

import React from 'react'

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      items: props.items,
    }
  }
}

Buglarla karşılaşabilirsiniz. çünkü yapıcı sadece denir bir Zamanlarbileşenin ilk oluşturulduğu zamandır.

Bir dahaki sefer propları değiştirmeye çalıştığınızda, yapıcı yeniden oluşturmalarda çağrılmayacağından durum önceki değerini koruyacaktır.

Henüz bu sorunla karşılaşmadıysanız, umarım bu size yardımcı olur!

Sahnelerin devletle nasıl senkronize edileceğini merak ediyorsanız, daha iyi bir yaklaşım şöyle olabilir:

import React from 'react'

class App extends React.Component {
  constructor(props) {
    super(props)
    
    this.state = {
      items: props.items,
    }
  }

  
  componentDidUpdate = (prevProps) => {
    const items = []
    
    if (...) {
      this.setState({ items })
    }
  }
}

7. Koşullu Oluşturma ile &&

Ortak Anladım bileşenleri koşullu olarak oluştururken && operatörünü kullanır.

React oluşturmayı deneyecek herhangi bir şey bir koşul gereksinimlerini karşılamıyorsa alternatif çıktı olarak sağlarsınız. Buna baktığımız zaman:

const App = ({ items = [] }) => (
  <div>
    <h2>Here are your items:</h2>
    <div>
      {items.length &&
        items.map((item) => <div key={item.label}>{item.label}</div>)}
    </div>
  </div>
)

Bu aslında bir sayı oluşturacak 0 ekranda ne zaman öğeler.uzunluk boş. JavaScript sayıyı dikkate alır 0 olarak falsey değeriÖyleyse ne zaman öğeler boş bir dizidir, && operatör, sağındaki ifadeyi değerlendirmeyecek ve sadece ilk değeri döndürecektir.

Sözdizimini korumak istersem genellikle yaptığım şey çift olumsuzlama kullanmaktır:

const App = ({ items = [] }) => (
  <div>
    <h2>Here are your items:</h2>
    <div>
      {!!items.length &&
        items.map((item) => <div key={item.label}>{item.label}</div>)}
    </div>
  </div>
)

Bu şekilde, eğer öğeler boş bir dizidir, değerlendirilen çıktı bir boole ise tepki ekranda hiçbir şey oluşturmaz.

8. Önceki Devletleri Yaymamak

Zaman zaman hata listeme girebilecek bir şey, durum güncelleme mantığının dikkatsizce uygulanmasından kaynaklanmaktadır.

Tepki kancalarını içeren yakın tarihli bir durum, özellikle bir kullanımRedüktör uygulama. İşte bunun bir sorun haline gelmesinin temel bir örneği:

const something = (state) => {
  let newState = { ...state }
  const indexPanda = newState.items.indexOf('panda')
  if (indexPanda !== -1) {
    newState.items.splice(indexPanda, 1)
  }
  return newState
}

const initialState = {
  items: [],
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'add-item':
      return { ...state, items: [...something(state).items, action.item] }
    case 'clear':
      return { ...initialState }
    default:
      return state
  }
}

Ne zaman bir şey işlev durumu çağırır ve kopyalar, altta yatan öğeler mülkiyet değişmedi. kullanarak mutasyona uğrattığımızda .splicebu mutasyona uğruyor durum.öğeler ve hataları tanıtacak.

Özellikle daha büyük kodda bu konuda yorgun olun. Muhtemelen hepimiz yukarıdaki gibi küçük bir örnekten geçeceğiz, ancak işler karıştığında, bu Her zaman Unutulması kolay olduğu için her zaman akılda tutulmalıdır, özellikle de kodu üretime göndermeniz için baskı altında olduğunuzda!

9. Yardımcı Öğeleri Açıkça Alt Bileşenlere Aktarmamak

Alt bileşenlere aktardığınız aksesuarlarda açık olmak genellikle önerilen bir uygulamadır.

Bunun birkaç iyi nedeni var:

  1. Daha Kolay Hata Ayıklama Deneyimi
    1. geliştirici olarak sen bilmek her çocuğa ne aktarılıyor.
      1. Diğer geliştiriciler de bunu bilecekler ve kodu okumak için daha kolay zamanları olacak.
  2. Bir Bileşenin Ne Yapacağını Anlamak Daha Kolay
    1. Sahne açıklığını aktarmanın bir başka harika yanı da, bunu yaptığınızda, kodunuzu, resmi bir belgeye bile ihtiyaç duymadan herkesin anlayabileceği şekilde belgeliyor olmasıdır. Ve şu zaman kazandırır!
  3. Olacak daha az bileşenin yeniden oluşturulup oluşturulmayacağını belirlemek için gerekli aksesuarlar.

orada olmasına rağmen Yapabilmek yaymak için oldukça temiz kullanım örnekleri olun tüm aksesuarlar.

Örneğin, bir ebeveyn, aksesuarları alt bileşenlere aktarmadan önce bir veya iki şeye çabucak ihtiyaç duyuyorsa, bunu yapmak onlar (ve sizin) için kolay olabilir:

const Parent = (props) => {
  if (props.user && props.user.email) {
    
    
  }

  
  return <Child {...props} />
}

Kendinizi böyle bir durumda bulmadığınızdan emin olun:

<ModalComponent
  open={aFormIsOpened}
  onClose={() => closeModal(formName)}
  arial-labelledby={`${formName}-modal`}
  arial-describedby={`${formName}-modal`}
  classes={{
    root: cx(classes.modal, { [classes.dialog]: shouldUseDialog }),
    ...additionalDialogClasses,
  }}
  disableAutoFocus
>
  <div>
    {!dialog.opened && (
      <ModalFormRoot
        animieId={animieId}
        alreadySubmitted={alreadySubmitted}
        academy={academy}
        user={user}
        clearSignature={clearSignature}
        closeModal={closeModal}
        closeImageViewer={closeImageViewer}
        dialog={dialog}
        fetchAcademyMember={fetchAcademyMember}
        formName={formName}
        formId={formId}
        getCurrentValues={getCurrentValues}
        header={header}
        hideActions={formName === 'signup'}
        hideClear={formName === 'review'}
        movieId={movie}
        tvId={tvId}
        openPdfViewer={openPdfViewer}
        onSubmit={onSubmit}
        onTogglerClick={onToggle}
        seniorMember={seniorMember}
        seniorMemberId={seniorMemberId}
        pdfViewer={pdfViewer}
        screenViewRef={screenViewRef}
        screenRef={screenRef}
        screenInputRef={screenInputRef}
        updateSignupFormValues={updateSignupFormValues}
        updateSigninFormValues={updateSigninFormValues}
        updateCommentFormValues={updateCommentFormValues}
        updateReplyFormValues={updateReplyFormValues}
        validateFormId={validateFormId}
        waitingForPreviousForm={waitingForPreviousForm}
        initialValues={getCurrentValues(formName)}
        uploadStatus={uploadStatus}
        uploadError={uploadError}
        setUploadError={setUploadError}
        filterRolesFalseys={filterRolesFalseys}
      />
    )}
  </div>
</ModalComponent>

Bunu yaparsanız, daha temiz ve daha özelleştirilebilir olması için bileşen parçalarını ayrı bileşenlere ayırmayı düşünün.

10. Pervane Delme

Sahne öğelerini birden çok alt bileşene geçirmek, buna “kod kokusu”.

Prop delmenin ne olduğunu bilmiyorsanız, bu bir ebeveynin sahne malzemelerini birden fazla bileşen seviyesi ağacın derinliklerinde.

Şimdi sorun ne ebeveyn ne de çocuk. Onlar uygulamalarını sürdürmeli aynısı. Bu Ortadaki bileşenler Tepki uygulamalarınızda bu bir sorun haline gelebilir.

Bunun nedeni, artık ortadaki bileşenlerin sıkı bir şekilde birbirine bağlanması ve ihtiyaç duymadıkları çok fazla bilgiye maruz kalmalarıdır. En kötü yanı, ebeveyn yeniden oluşturduğunda, ortadaki bileşenler de yeniden oluşturulacakzincirdeki tüm alt bileşenlere domino etkisi yapıyor.

kullanmak iyi bir çözümdür. bağlam yerine. Veya alternatif olarak, redux sahne için (bunun sonucunda ancak seri hale getirilecek).

Çözüm

Bu yazının sonunu getiriyor 🙂 Umarım bu makaleyi sizin için yararlı bulmuşsunuzdur ve gelecekteki gönderiler için beni medyadan takip ettiğinizden emin olun!

Bir cevap yazın

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