Коли використовувати компоненти React на основі класу ES6 проти функціональних компонентів ES6 React?


211

Провівши деякий час на вивчення React, я розумію різницю між двома основними парадигмами створення компонентів.

Моє запитання - коли я повинен використовувати який і чому? Які переваги / компроміси однієї над іншою?


ES6 класи:

import React, { Component } from 'react';

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

Функціональні:

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

Я думаю, що я функціональний, коли не існує стану, яким маніпулює цей компонент, але це так?

Я здогадуюсь, що якщо я використовую будь-які методи життєвого циклу, можливо, найкраще працювати з компонентом на основі класу.


7
Здається, ви вже знаєте відповідь.
Фелікс Клинг

2
Якщо у вас є компонент лише з методом візуалізації, ви можете перетворити його у функціональну форму. Якщо вам потрібно щось більше, ніж функція візуалізації без громадянства, використовуйте класи
just-boris

2
Щоб бути ще більш стислим, спробуйте це:const MyComponent = (props) => <div>...</div>
Віліам Сімко

1
Я ніколи не використовую функціонал, якщо цього можна уникнути. Тому що мені неминуче в кінцевому підсумку потрібно перейматись на класичний вниз дорогу. А потім часто після цього потрібно переробити функціонал.
keithjgrant

У 2020 році правильним підходом є використання функціональних компонентів, де це можливо, оскільки вони підтримують гачки, а гачки (ефективні та архітектурно) кращі, ніж альтернативи.
polkovnikov.ph

Відповіді:


161

Ви маєте правильну ідею. Займіться функціоналом, якщо ваш компонент не набагато більше, ніж зайняти деякі реквізити та візуалізувати. Ви можете думати про це як про чисті функції, оскільки вони завжди будуть відображатись та поводяться однаково, враховуючи однакові реквізити. Крім того, вони не переймаються методами життєвого циклу або мають власний внутрішній стан.

Оскільки вони легкі, писати ці прості компоненти як функціональні компоненти досить стандартно.

Якщо ваші компоненти потребують більшої функціональності, як-от утримання стану, замість цього використовуйте класи.

Більше інформації: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


EDIT : Багато з сказаного було правдою, аж до введення React Hooks.

  • componentDidUpdateможе бути реплікувати з useEffect(fn), де fnфункція, яку потрібно запустити при повторній передачі.

  • componentDidMountМетоди можуть бути тиражовані useEffect(fn, []), де fnфункція, яку потрібно запустити при повторному рендерингу, і []являє собою масив об'єктів, для яких компонент буде рендерувати, якщо і тільки якщо принаймні один змінено значення з попереднього візуалізації. Оскільки їх немає, useEffect()запускається один раз на першому монтажі.

  • stateможна реплікувати з useState(), повернене значення якого може бути зруйновано на посилання на стан і функцію, яка може встановити стан (тобто const [state, setState] = useState(initState)). Приклад може пояснити це більш чітко:

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

Щодо рекомендації щодо використання класу над функціональними компонентами, Facebook офіційно рекомендує використовувати функціональні компоненти, де це можливо . Як невеличкий бік, я чув, як ряд людей обговорювали не використання функціональних компонентів з міркувань продуктивності, зокрема

"Функції обробки подій переосмислюються за візуалізацією у функціональних компонентах"

Незважаючи на це правда, будь ласка, врахуйте, чи справді ваші компоненти відображаються з такою швидкістю чи обсягом, що це варто занепокоїти.

Якщо вони є, ви можете запобігти перевизначення функції , використовуючи useCallbackі useMemoгачки. Однак майте на увазі, що це може покращити ваш код (мікроскопічно) в роботі .

Але, чесно кажучи, я ніколи не чув, щоб переосмислити функції як вузьке місце в програмах React. Передчасні оптимізації - корінь усього зла - переживайте про це, коли це проблеми


Що щодо функціональності, який не підтримує стан, але тісно пов'язаний з компонентом, наприклад, визначте якийсь динамічний атрибут для візуалізації.
Денніс

Це найкраща стаття про різницю між двома типами компонентів у React: code.tutsplus.com/tutorials/…
Arian Acosta

5
Станом на React 16.8, ви можете використовувати стан у функціональному компоненті через useStateгачок.
Грег

Станом на React 16.8, ви можете робити майже все у функціональних компонентах, і всі ефекти, нарешті, можна модулювати лише з мінімальним впливом на продуктивність.
polkovnikov.ph

1
Де ти знайшов інформацію де Facebook officially recommends using functional components wherever possible?
johannchopin

40

Завжди намагайтеся використовувати функції без стану (функціональні компоненти), коли це можливо. Є сценарії, коли вам потрібно буде використовувати звичайний клас React:

  • Компонент повинен підтримувати стан
  • Компонент занадто багато відтворює, і вам потрібно контролювати це через shouldComponentUpdate
  • Вам потрібен компонент контейнера

ОНОВЛЕННЯ

Зараз клас React називається, PureComponentщо ви можете розширити (замість Component), який реалізує свій власний, shouldComponentUpdateякий піклується про порівняння для вас дрібних реквізитів. Детальніше


43
Always try to use stateless functions (functional components) whenever possible.Я читав, що десять людей говорять про це. Досі ніхто з них не дав пояснення, чому.
Ротарети

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.Більше інформації: facebook.github.io/react/docs/…
Diogo Cardoso

2
@rotareti Я не знаю, чи відчуваєте ви відповідь на запитання, але чисті функції набагато простіші для розуміння, тестування та підтримки. Враховуючи однакові параметри, вони завжди представляють одне і те ж. Компоненти, які підтримують стан і змінюються, коли відбуваються події життєвого циклу, важче зрозуміти. Не кажучи про те, що вони іноді не потрібні, але я сподіваюся, що зрозуміло, що якщо їх переваги не потрібні, все, що вони роблять, - це додавати небажані котлопластини та накладні витрати без користі.
door_number_three

Ви також захочете створити клас компонентів, якщо у вас є власні визначення обробника подій. Таким чином ви можете попередньо прив’язати ці обробники подій до компонента в конструкторі, а не створювати нову функцію для кожного візуалізації. Зверніть увагу, що це не потрібно, якщо всі ваші обробники подій походять від реквізиту.
Dobes Vandermeer

Зауважте, що цитована рекомендація Facebook більше не існує (див. Мій коментар вище).
Гаррет

34

ОНОВЛЕННЯ березень 2019 року

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

ОНОВЛЕННЯ Лютий 2019:

Завдяки впровадженню гачків React , схоже, команди React хочуть, щоб ми використовували функціональні компоненти, коли це можливо (що краще відповідає функціональному характеру JavaScript).

Їх мотивація:

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

Функціональний компонент з гачками може робити майже все, що може зробити компонент класу, без жодного з зворотних зворотів.

Я рекомендую використовувати їх, як тільки зможете.

Оригінальний відповідь

Функціональні компоненти не легші, ніж компоненти на основі класу, "вони виконуються точно як класи". - https://github.com/facebook/react/isissue/5677#issuecomment-241190513

Наведене вище посилання трохи датоване, але документація React 16.7.0 говорить про те, що функціональні та класові компоненти:

"еквівалентні з точки зору Реакти". - https://reactjs.org/docs/components-and-props.html#stateless-functions

По суті немає різниці між функціональним компонентом і компонентом класу, який просто реалізує метод візуалізації, крім синтаксису.

Надалі (цитуючи вищезазначене посилання) "ми [Реагуємо] можемо додати такі оптимізації."

Якщо ви намагаєтеся підвищити ефективність, усуваючи зайві візуалізації, обидва підходи надають підтримку. memoдля функціональних компонентів та PureComponentдля занять.

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

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

Це справді залежить від вас. Якщо ви хочете менше котла, переходьте до функціоналу. Якщо ви любите функціональне програмування і не любите заняття, переходьте до функціоналу. Якщо ви хочете узгодженість між усіма компонентами вашої кодової бази, перейдіть до класів. Якщо вам набридло переробити з функціональних компонентів на компоненти класу, коли вам потрібно щось подібне state, займіться класами.


1
Я думаю, що зробивши кожен компонент розширеним React.Component робить код більш читабельним, особливо для нових людей. Приємно, коли бачиш компонент, створений однаково кожен раз. Як сказав @Galupuf, прості компоненти просто мають один метод, який називається "render ()". Також приємно зробити все розширеним React.Component, тому що коли ви хочете почати прив'язувати "це", маючи стан і т. Д., Вам не доведеться все рефактувати, ви можете просто додати те, що вам потрібно.
jeffski13

10

Згідно з Реактом 16.8, термін функціональних компонентів без громадянства вводить в оману, і їх слід уникати, оскільки вони більше не стають без громадянства ( React.SFC застарів , Дан Абрамов на React.SFC ), вони можуть мати стан, вони можуть мати гачки (які виконують роль методи життєвого циклу) також вони більш-менш перетинаються з компонентами класу

Компоненти на основі класу

  • держава
  • методи життєвого циклу
  • запам'ятовування за допомогою React.PureComponent

Функціональні компоненти:

Чому я віддаю перевагу функціональним компонентам

  • Реагувати забезпечує useEffect гак , який є дуже чітким і лаконічним способом об'єднати componentDidMount, componentDidUpdateі componentWillUnmountметоди життєвого циклу
  • За допомогою гачків ви можете витягти логіку, яку можна легко поділити між компонентами та перевірити
  • менша плутанина щодо масштабування

Реагуйте на мотивацію того, чому використовуєте гачки (тобто функціональні компоненти).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.