ES6 sınıfı tabanlı React bileşenleri ile işlevsel ES6 React bileşenleri ne zaman kullanılır?


212

Tepki öğrenmek için biraz zaman geçirdikten sonra, bileşen yaratmanın iki ana paradigması arasındaki farkı anlıyorum.

Sorum şudur, hangisini ve ne zaman kullanmalıyım? Birinin diğerinin yararları / değişimleri nelerdir?


ES6 sınıfları:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

Fonksiyonel:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

Bu bileşen tarafından manipüle edilecek bir durum olmadığında işlevsel düşünüyorum, ama öyle mi?

Ben herhangi bir yaşam döngüsü yöntemleri kullanırsanız, sınıf tabanlı bir bileşen ile gitmek en iyi olabilir tahmin ediyorum.


7
Görünüşe göre cevabı biliyorsunuz.
Felix Kling

2
Yalnızca oluşturma yöntemine sahip bir bileşeniniz varsa, bunu işlevsel forma dönüştürebilirsiniz. Vatansız oluşturma işlevinden daha fazlasına ihtiyacınız varsa, sınıfları kullanın
just-boris

2
Daha da özlü olmak için şunu deneyin:const MyComponent = (props) => <div>...</div>
Viliam Simko

1
Önlenebilirse asla işlevsel kullanmam. Çünkü kaçınılmaz olarak sınıf temelli bir yoldan yeniden düzenleme ihtiyacım var. Ve daha sonra bundan sonra tekrar işlevselliğe geri dönmesi gerekir.
keithjgrant

2020'de doğru yaklaşım, mümkün olduğunda fonksiyonel bileşenleri kullanmaktır, çünkü kancaları desteklerler ve kancalar (performans açısından ve mimari olarak) alternatiflerden daha iyidir.
polkovnikov.ph

Yanıtlar:


161

Doğru fikre sahipsiniz. Bileşeniniz bazı sahne ve render almaktan daha fazlasını yapmazsa işlevsel hale geçin. Bunları saf işlevler olarak düşünebilirsiniz, çünkü aynı sahne öğeleri göz önüne alındığında her zaman aynı şekilde davranacak ve davranacaklardır. Ayrıca, yaşam döngüsü yöntemleri ile ilgilenmezler veya kendi iç durumlarına sahiptirler.

Hafif olduklarından, bu basit bileşenleri işlevsel bileşenler olarak yazmak oldukça standarttır.

Bileşenlerinizin durum koruma gibi daha fazla işlevselliğe ihtiyacı varsa, bunun yerine sınıfları kullanın.

Daha fazla bilgi: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


DÜZENLEME : Tepki Kancaları tanıtılıncaya kadar yukarıdakilerin çoğu doğruydu.

  • componentDidUpdateile çoğaltılabilir useEffect(fn), fnyeniden oluşturma sırasında çalıştırılacak işlev nerede .

  • componentDidMountyöntemlerle çoğaltılabilir useEffect(fn, []), burada fnyeniden oluşturma sırasında çalıştırılacak işlev vardır []ve yalnızca önceki oluşturma işleminden bu yana en az bir değer değiştiyse, bileşenin yeniden gönderileceği bir nesne dizisidir. Hiçbiri olmadığından, useEffect()ilk montajda bir kez çalışır.

  • stateuseState()dönüş değeri durumun bir referansına ve durumu ayarlayabilen bir işleve (yani, const [state, setState] = useState(initState)) tahrip edilebilen ile çoğaltılabilir . Bir örnek bunu daha açık bir şekilde açıklayabilir:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

Sınıfın fonksiyonel bileşenler üzerinde ne zaman kullanılacağına dair tavsiyeyle ilgili olarak, Facebook resmi olarak mümkün olan her yerde fonksiyonel bileşenlerin kullanılmasını önerir . Küçük bir kenara, performans nedenleriyle fonksiyonel bileşenleri kullanmadığını tartışan birkaç kişinin duydum, özellikle

"Olay işleme işlevleri, işlevsel bileşenlerde oluşturma başına yeniden tanımlanıyor"

Doğru olsa da, lütfen bileşenlerinizin gerçekten kaygılanmaya değer bir hızda veya hacimde oluşturulup oluşturulmadığını düşünün.

Öyleyse useCallbackve useMemokancaları kullanarak işlevleri yeniden tanımlamayı önleyebilirsiniz . Ancak, bunun kodunuzu (mikroskopik olarak) performansta daha kötü hale getirebileceğini unutmayın .

Ama dürüst olmak gerekirse, React uygulamalarında bir darboğazın yeniden tanımlandığını hiç duymadım. Erken optimizasyonlar tüm kötülüklerin köküdür - bir sorun olduğunda endişelen


Durumu korumayan, ancak bileşene sıkı sıkıya bağlı olan işlevsellik hakkında, örneğin, işleme için bazı dinamik öznitelikleri belirleme.
Dennis


5
React 16.8'den itibaren, fonksiyonel bir bileşendeki durumu useStatekanca ile kullanabilirsiniz.
Greg

React 16.8'den itibaren fonksiyonel bileşenlerde neredeyse her şeyi yapabilirsiniz ve tüm efektler nihayet performans üzerinde minimum bir etki ile modüler hale getirilebilir.
polkovnikov.ph

1
Bilgileri nerede buldun nerede Facebook officially recommends using functional components wherever possible?
johannchopin

40

Mümkün olduğunca daima durum bilgisi olmayan işlevleri (işlevsel bileşenler) kullanmaya çalışın. Normal bir React sınıfı kullanmanız gereken senaryolar vardır:

  • Bileşenin durumu koruması gerekir
  • Bileşen çok fazla yeniden oluşturuluyor ve bunu kontrol etmeniz gerekiyor shouldComponentUpdate
  • Bir kapsayıcı bileşenine ihtiyacınız var

GÜNCELLEME

Şimdi PureComponentsizin için sığ sahne karşılaştırması ilgilenen Componentkendi uygulayan genişletmek (yerine ) denilen bir React sınıfı shouldComponentUpdatevar. Daha fazla oku


43
Always try to use stateless functions (functional components) whenever possible.Ben on kişi bunu söyledi okudum. Hala hiçbiri nedenini açıklamadı.
Rotareti

25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.Daha fazla bilgi: facebook.github.io/react/docs/…
Diogo Cardoso

2
@rotareti Sorunuzu cevapladığını hissediyor musunuz bilmiyorum, ama saf fonksiyonları anlamak, test etmek ve korumak çok daha kolaydır. Aynı parametreler göz önüne alındığında, her zaman aynı şeyi yaparlar. Yaşam döngüsü olayları gerçekleştiğinde durumu koruyan ve değiştiren bileşenleri anlamak daha zordur. Bazen ihtiyaç duyulmadıklarını söylememekle birlikte, umarım avantajları gerekli değilse, tüm yaptıkları istenmeyen kazan plakası ve ek yük olmadan fayda sağlamaktır.
door_number_three

Kendi olay işleyici tanımlarınız varsa bir Bileşen sınıfı oluşturmak da isteyeceksiniz. Bu şekilde her olayda yeni bir işlev oluşturmak yerine bu olay işleyicilerini yapıcıdaki bileşene önceden bağlayabilirsiniz. Tüm olay işleyicileriniz sahne kaynaklarından geliyorsa bunun gerekli olmadığını unutmayın.
Dobes Vandermeer

Alıntı Facebook önerisi (bkz artık mevcut olduğunu Not yorumumu üstünde).
Garrett

34

GÜNCELLEME Mart 2019

https://overreacted.io/how-are-function-components-different-from-classes/

GÜNCELLEME Şubat 2019:

React kancalarının piyasaya sürülmesiyle , React ekipleri mümkün olduğunda fonksiyonel bileşenleri kullanmamızı istiyor gibi görünüyor (bu da JavaScript'in işlevsel doğasını daha iyi takip ediyor).

Motivasyonları:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

Kancalı fonksiyonel bir bileşen, bir sınıf bileşeninin yapabileceği neredeyse her şeyi, yukarıda belirtilen herhangi bir geri çekme olmadan yapabilir.

Bunları mümkün olan en kısa sürede kullanmanızı öneririm.

Orijinal Yanıt

Fonksiyonel bileşenler sınıf tabanlı bileşenlerden daha hafif değildir, "tam olarak sınıf olarak çalışırlar." - https://github.com/facebook/react/issues/5677#issuecomment-241190513

Yukarıdaki bağlantı biraz tarihli, ancak React 16.7.0'ın belgeleri işlevsel ve sınıf bileşenlerini söylüyor:

"React'in bakış açısından eşdeğerdir." - https://reactjs.org/docs/components-and-props.html#stateless-functions

İşlevsel bir bileşen ile sözdizimi dışında yalnızca oluşturma yöntemini uygulayan bir sınıf bileşeni arasında hiçbir fark yoktur.

Gelecekte (yukarıdaki bağlantıdan alıntı yaparak) "biz [React] bu tür optimizasyonlar ekleyebiliriz."

Gereksiz render'ları ortadan kaldırarak performansı artırmaya çalışıyorsanız, her iki yaklaşım da destek sağlar. memofonksiyonel bileşenler ve PureComponentsınıflar için.

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

Gerçekten size kalmış. Daha az kazan plakası istiyorsanız, işlevsel olun. Fonksiyonel programlamayı seviyorsanız ve sınıfları sevmiyorsanız, işlevsel olun. Kod tabanınızdaki tüm bileşenler arasında tutarlılık istiyorsanız sınıflarla devam edin. Gibi bir şeye ihtiyacınız olduğunda işlevselden sınıf tabanlı bileşenlere yeniden düzenleme yapmaktan bıktıysanız, statesınıflarla devam edin.


1
Her bileşeni React.Component uzatmak, özellikle yeni insanlar için kodu daha okunabilir hale düşünüyorum. Bir bileşenin her seferinde aynı şekilde oluşturulduğunu görmek güzel. @Galupuf'un dediği gibi, basit bileşenler sadece "render ()" adında bir yönteme sahiptir. Her şeyin React.Component'i genişletmesi de güzeldir, çünkü "bu" bağlamaya başlamak istediğinizde, duruma sahip olmak vb. Her şeyi yeniden düzenlemek zorunda kalmazsınız, sadece ihtiyacınız olanı ekleyebilirsiniz.
jeffski13

10

Tepki 16.8'den itibaren Vatansız Fonksiyonel bileşenler yanıltıcıdır ve bundan kaçınılmalıdır çünkü artık vatansız değildir ( React.SFC kullanımdan kaldırılmıştır , React.SFC'de Dan Abramov ), bir durumları olabilir, kancaları olabilir ( yaşam döngüsü yöntemleri) de, aşağı yukarı sınıf bileşenleri ile çakışıyor

Sınıf tabanlı bileşenler

Fonksiyonel bileşenler:

Neden Funtional bileşenleri tercih ederim

  • Birleştirmek için çok açık ve özlü bir yoldur useEffect kanca sağlamak tepki componentDidMount, componentDidUpdateve componentWillUnmountyaşam döngüsü yöntemleri
  • Kancalarla , bileşenler ve test edilebilirler arasında kolayca paylaşılabilen mantık çıkarabilirsiniz
  • kapsam belirleme konusunda daha az karışıklık

Kancaların (yani fonksiyonel bileşenlerin) kullanılmasına neden olan tepki motivasyonu .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.