Kiedy stosować komponenty React oparte na klasie ES6 a funkcjonalne komponenty React ES6?

211

Po spędzeniu czasu na nauce React rozumiem różnicę między dwoma głównymi paradygmatami tworzenia komponentów.

Moje pytanie brzmi: kiedy powinienem użyć którego i dlaczego? Jakie są zalety / kompromisy jednego nad drugim?


Klasy ES6:

import React, { Component } from 'react';

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

Funkcjonalny:

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

Myślę, że jest funkcjonalny, ilekroć nie ma stanu, którym mógłby manipulować ten komponent, ale czy to jest to?

Zgaduję, że jeśli użyję jakichkolwiek metod cyklu życia, może być lepiej, aby użyć komponentu opartego na klasach.

omarjmh
źródło
7
Wygląda na to, że znasz już odpowiedź.
Felix Kling
2
Jeśli masz komponent tylko z metodą renderowania, możesz go przekształcić w formę funkcjonalną. Jeśli potrzebujesz czegoś więcej niż funkcji renderowania bezstanowego, skorzystaj z klas
just-boris
2
Aby być jeszcze bardziej zwięzłym, spróbuj tego:const MyComponent = (props) => <div>...</div>
Viliam Simko
1
Nigdy nie używam funkcjonalnych, jeśli można tego uniknąć. Ponieważ nieuchronnie muszę zrezygnować z pracy w klasie. A potem często trzeba potem zrefaktoryzować z powrotem do funkcjonalności.
keithjgrant
W 2020 r. Poprawnym podejściem jest stosowanie funkcjonalnych komponentów tam, gdzie to możliwe, ponieważ obsługują one haki, a haki są (pod względem wydajności i architektury) lepsze niż alternatywy.
polkovnikov.ph

Odpowiedzi:

161

Masz dobry pomysł. Idź z funkcjonalnością, jeśli twój komponent nie robi nic więcej niż przyjmowanie niektórych rekwizytów i renderowanie. Możesz myśleć o nich jako o czystych funkcjach, ponieważ zawsze będą renderować i zachowywać się tak samo, biorąc pod uwagę te same rekwizyty. Nie dbają też o metody cyklu życia ani nie mają własnego stanu wewnętrznego.

Ponieważ są one lekkie, pisanie tych prostych elementów jako elementów funkcjonalnych jest dość standardowe.

Jeśli komponenty wymagają większej funkcjonalności, np. Utrzymania stanu, użyj klas.

Więcej informacji: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


EDYCJA : Wiele z powyższych było prawdą, dopóki nie wprowadzono React Hooks.

  • componentDidUpdatemożna zreplikować za pomocą useEffect(fn), gdzie fnjest funkcja uruchamiana przy ponownym renderowaniu.

  • componentDidMountmetody mogą być replikowane useEffect(fn, []), gdzie fnjest funkcja uruchamiana przy ponownym renderowaniu, i []jest tablicą obiektów, dla których komponent ponownie się wyrenderuje, tylko wtedy, gdy przynajmniej jedna zmieniła wartość od poprzedniego renderowania. Ponieważ ich nie ma, useEffect()uruchamia się raz na pierwszym montażu.

  • statemoże być zreplikowany useState(), którego wartość zwracaną można zniszczyć do odwołania do stanu i funkcji, która może ustawić stan (tj const [state, setState] = useState(initState).). Przykład może to wyjaśnić jaśniej:

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

Jeśli chodzi o zalecenie, kiedy stosować klasę zamiast komponentów funkcjonalnych, Facebook oficjalnie zaleca używanie komponentów funkcjonalnych tam, gdzie to możliwe . Nawiasem mówiąc, słyszałem wiele osób dyskutujących o nieużywaniu komponentów funkcjonalnych ze względu na wydajność, a konkretnie z tego powodu

„Funkcje obsługi zdarzeń są redefiniowane dla poszczególnych renderów w komponentach funkcjonalnych”

Chociaż to prawda, zastanów się, czy Twoje komponenty naprawdę renderują z taką prędkością lub głośnością, że byłoby to warte zaniepokojenia.

Jeśli tak, możesz zapobiec przedefiniowaniu funkcji za pomocą useCallbacki useMemohooków. Należy jednak pamiętać, że może to pogorszyć działanie (mikroskopowo) kodu .

Ale szczerze mówiąc, nigdy nie słyszałem o ponownym definiowaniu funkcji stanowiących wąskie gardło w aplikacjach React. Przedwczesne optymalizacje są źródłem wszelkiego zła - martw się o to, gdy jest to problem

Jeff Cousins
źródło
Co z funkcjonalnością, która nie utrzymuje stanu, ale jest ściśle powiązana ze składnikiem, np. Określa jakiś dynamiczny atrybut renderowania.
Dennis
To jest najlepszy artykuł na temat różnicy między dwoma typami komponentów w React: code.tutsplus.com/tutorials/…
Arian Acosta
5
Od React 16.8 można użyć stanu w komponencie funkcjonalnym za pośrednictwem useStatehaka.
Greg
Począwszy od React 16.8, możesz zrobić prawie wszystko w funkcjonalnych komponentach, a wszystkie efekty można w końcu zmodularyzować przy minimalnym wpływie na wydajność.
polkovnikov.ph
1
Gdzie znajdziesz informacje gdzie Facebook officially recommends using functional components wherever possible?
johannchopin
40

Zawsze staraj się używać funkcji bezstanowych (komponentów funkcjonalnych), gdy tylko jest to możliwe. Istnieją scenariusze, w których musisz użyć zwykłej klasy React:

  • Komponent musi utrzymać stan
  • Komponent renderuje zbyt wiele i należy to kontrolować za pośrednictwem shouldComponentUpdate
  • Potrzebujesz komponentu kontenera

AKTUALIZACJA

Istnieje teraz klasa React PureComponent, którą można rozszerzyć (zamiast Component), która implementuje swoją własną, shouldComponentUpdatektóra dba o porównanie płytkich rekwizytów. Czytaj więcej

ffxsam
źródło
43
Always try to use stateless functions (functional components) whenever possible.Przeczytałem, że dziesięć osób tak mówi. Nadal żaden z nich nie wyjaśnił, dlaczego.
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.Więcej informacji: facebook.github.io/react/docs/…
Diogo Cardoso,
2
@rotareti Nie wiem, czy uważasz, że otrzymałeś odpowiedź na swoje pytanie, ale czyste funkcje są znacznie prostsze do zrozumienia, przetestowania i utrzymania. Biorąc pod uwagę te same parametry, zawsze renderują to samo. Komponenty, które utrzymują stan i zmieniają się po wystąpieniu zdarzeń cyklu życia, są trudniejsze do zrozumienia. Nie mówiąc już, że czasami nie są potrzebne, ale mam nadzieję, że jasne jest, że jeśli ich zalety nie są potrzebne, wszystko, co robią, to dodawanie niepożądanej płyty grzewczej i napowietrznych bez żadnych korzyści.
door_number_three
Będziesz także chciał utworzyć klasę Component, jeśli masz własne definicje procedur obsługi zdarzeń. W ten sposób możesz wstępnie powiązać te procedury obsługi zdarzeń ze składnikiem w konstruktorze zamiast tworzyć nową nową funkcję na każdym renderowaniu. Uwaga: nie jest to konieczne, jeśli wszystkie programy obsługi zdarzeń pochodzą z rekwizytów.
Dobes Vandermeer
Pamiętaj, że cytowana rekomendacja na Facebooku już nie istnieje (patrz mój komentarz powyżej).
Garrett
34

AKTUALIZACJA Marzec 2019

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

AKTUALIZACJA Luty 2019:

Wraz z wprowadzeniem haków React wydaje się, że zespoły React chcą, abyśmy korzystali z funkcjonalnych komponentów, gdy tylko jest to możliwe (co lepiej odpowiada funkcjonalnej naturze JavaScript).

Ich motywacja:

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

Funkcjonalny komponent z haczykami może zrobić prawie wszystko, co może zrobić komponent klasy, bez żadnej z wymienionych powyżej wad.

Zalecam ich użycie, gdy tylko będzie to możliwe.

Oryginalna odpowiedź

Komponenty funkcjonalne nie są bardziej lekkie niż komponenty oparte na klasach, „działają dokładnie jak klasy”. - https://github.com/facebook/react/issues/5677#issuecomment-241190513

Powyższe łącze jest trochę przestarzałe, ale dokumentacja React 16.7.0 mówi, że komponenty funkcjonalne i klasowe:

„są równoważne z punktu widzenia React”. - https://reactjs.org/docs/components-and-props.html#stateless-functions

Zasadniczo nie ma różnicy między komponentem funkcjonalnym a komponentem klasy, który właśnie implementuje metodę renderowania, inną niż składnia.

W przyszłości (cytując powyższy link) „my [React] możemy dodać takie optymalizacje”.

Jeśli próbujesz zwiększyć wydajność, eliminując niepotrzebne rendery, oba podejścia zapewniają wsparcie. memodla komponentów funkcjonalnych i PureComponentdla klas.

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

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

To naprawdę zależy od ciebie. Jeśli chcesz mniej płyty kotła, działaj. Jeśli kochasz programowanie funkcjonalne i nie lubisz zajęć, wybierz funkcjonalność. Jeśli chcesz uzyskać spójność między wszystkimi komponentami w bazie kodu, idź z klasami. Jeśli masz dość refaktoryzacji komponentów od funkcjonalnych do klasowych, kiedy potrzebujesz czegoś takiego state, idź z klasami.

Galupuf
źródło
1
Myślę, że rozszerzenie każdego komponentu React.Component sprawia, że ​​kod jest bardziej czytelny, szczególnie dla nowych osób. Miło jest widzieć komponent tworzony za każdym razem w ten sam sposób. Jak powiedział @Galupuf, proste komponenty mają tylko jedną metodę o nazwie „render ()”. Przyjemnie jest również, aby wszystko rozszerzało React.Component, ponieważ gdy chcesz zacząć wiązać „to”, posiadanie stanu itp., Nie musisz wszystko refaktoryzować, możesz po prostu dodać to, czego potrzebujesz.
jeffski13
10

Od React 16.8 termin Bezstanowe elementy funkcjonalne są mylące i należy ich unikać, ponieważ nie są one już bezpaństwowcami ( React.SFC przestarzałe , Dan Abramov na React.SFC ), mogą mieć stan, mogą mieć haki (które działają jak metody cyklu życia), pokrywają się one mniej więcej z komponentami klasy

Komponenty oparte na klasach

Komponenty funkcjonalne:

Dlaczego wolę komponenty Funtional

  • React dostarczyć hak useEffect który jest bardzo jasny i zwięzły sposób, aby połączyć componentDidMount, componentDidUpdatea componentWillUnmountmetody cyklu życia
  • Za pomocą haczyków można wyodrębnić logikę, którą można łatwo udostępnić między komponentami i przetestować
  • mniej zamieszania na temat określania zakresu

Reaguj motywację, dlaczego używasz haczyków (tj. Elementów funkcjonalnych).

Karim
źródło