Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Життєвий цикл класового VS функціонального компонента». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Класові компоненти керують життєвим циклом через **окремі методи** (`componentDidMount`, `componentDidUpdate`, `componentWillUnmount`), а функціональні - через **хуки** (`useEffect`), які об'єднують усю логіку в одному місці. **Ключове:** хуки дають гнучкіший і універсальніший спосіб керувати тими самими моментами життєвого циклу, що й методи класу.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Головна відмінність | Класові компоненти | Функціональні компоненти | | --- | --- | | Використовують **методи життєвого циклу** (`componentDidMount`, `componentDidUpdate`, `componentWillUnmount` та ін.) | Використовують **хуки** (`useEffect`, `useLayoutEffect`, `useMemo` тощо) | | React **сам викликає** методи в потрібний момент | Хуки дають тобі **гнучкіший** і **універсальніший** спосіб керувати цими моментами | | Логіка "розкидана" по різних методах | Логіка "зібрана" в одному місці і може бути винесена в кастомні хуки | --- ## Життєвий цикл класового компонента ### Основні стадії та методи: | Стадія | Метод | Коли викликається | Аналог у хуках | | --- | --- | --- | --- | | **Монтування** | `constructor()` | При створенні екземпляра класу | - | | | `componentDidMount()` | Після першого рендеру і вставлення в DOM | `useEffect(() => {...}, [])` | | **Оновлення** | `componentDidUpdate(prevProps, prevState)` | Після оновлення `state` або `props` | `useEffect(() => {...}, [deps])` | | **Розмонтування** | `componentWillUnmount()` | Перед видаленням з DOM | `useEffect(() => { return () => {...} }, [])` | --- ### Приклад (класичний) ```javascript class Timer extends React.Component { state = { seconds: 0 }; componentDidMount() { this.interval = setInterval(() => { this.setState({ seconds: this.state.seconds + 1 }); }, 1000); } componentWillUnmount() { clearInterval(this.interval); } render() { return <p>Минуло секунд: {this.state.seconds}</p>; } } ``` --- ## Життєвий цикл функціонального компонента У "функціональному світі" немає окремих методів - усе вирішується за допомогою **хуків**. Основний інструмент - `useEffect`. ### Аналоги стадій: | Стадія | Як реалізується | | --- | --- | | **Монтування** | `useEffect(() => {...}, [])` | | **Оновлення** | `useEffect(() => {...}, [deps])` | | **Розмонтування** | `useEffect(() => { return () => {...} }, [])` | --- ### Приклад (еквівалент через хуки) ```javascript function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const id = setInterval(() => setSeconds(s => s + 1), 1000); return () => clearInterval(id); // cleanup - аналог componentWillUnmount }, []); return <p>Минуло секунд: {seconds}</p>; } ``` --- ## Ключові відмінності в підході | № | Класовий компонент | Функціональний компонент | | --- | --- | --- | | 1 | Розділений на методи (`componentDidMount`, `componentDidUpdate`, …) | Усе робиться всередині `useEffect` із залежностями | | 2 | Логіка "розмазана" по різних місцях | Логіка згрупована за змістом (хуки можна виносити в кастомні) | | 3 | Має `this` і стан через `this.state` / `this.setState` | Використовує `useState` / `useReducer`, без `this` | | 4 | `setState` - завжди асинхронний і об'єднує об'єкти | `useState` - працює з будь-якими типами даних, включно з об'єктами і функціями | | 5 | Один екземпляр класу живе весь час | Функція викликається заново при кожному рендері | | 6 | Важко перевикористовувати логіку (тільки HOC або render props) | Легко ділити й перевикористовувати через **кастомні хуки** | | 7 | Більш "імперативний" стиль | Більш "декларативний" і функціональний стиль | --- ## Ілюстрація ### Класовий підхід: ```javascript constructor() ↓ render() ↓ componentDidMount() ↓ componentDidUpdate() ↓ componentWillUnmount() ``` ### Функціональний підхід: ```javascript Рендер → useEffect(() => {...}, []) Рендер → useEffect(() => {...}, [deps]) Unmount → cleanup() ``` --- ## Чому React перейшов до хуків - Хуки спрощують код: менше шаблонного коду (`this`, bind, конструктор). - Дозволяють **розділяти логіку за змістом**, а не за стадіями. - Спрощують перевикористання логіки (через кастомні хуки). - Краще працюють із TypeScript і функціональним стилем. - Підтримують **Concurrent Rendering** (React 18+). --- ## Підсумок | Аспект | Класовий компонент | Функціональний компонент | | --- | --- | --- | | API життєвого циклу | Методи (`componentDidMount`, `componentDidUpdate`, `componentWillUnmount`) | Хуки (`useEffect`, `useLayoutEffect`, cleanup-функції) | | Стан | `this.state` + `this.setState()` | `useState`, `useReducer` | | Контекст | `contextType` | `useContext()` | | Складність логіки | Розкидана по методах | Сфокусована в хуках | | Повторне використання | Через HOC/render props | Через **кастомні хуки** | | "this" | Є | Немає | | Продуктивність / зручність | Більш громіздкий | Більш декларативний і гнучкий | --- **Головна ідея:** > Класові компоненти керують життєвим циклом через **окремі методи**, > а функціональні - через **хуки (**`useEffect`**)**, > які об'єднують усю життєву логіку в одному місці і дозволяють легко її перевикористовувати.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.