Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чим React.memo() схожий на shouldComponentUpdate()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)І **`React.memo()`**, і **`shouldComponentUpdate()`** дозволяють **контролювати, чи має компонент перерендерюватися**, якщо його `props` не змінилися. **Ключове:** обидва потрібні для оптимізації продуктивності - щоб уникнути зайвих ререндерів, коли компонент отримує ті самі дані.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Загальна ідея > І `React.memo()`, і `shouldComponentUpdate()` дозволяють **контролювати, чи має компонент перерендерюватися**, > якщо його `props` не змінилися. Обидва потрібні для **оптимізації продуктивності** - щоб уникнути **зайвих ререндерів**, коли компонент отримує ті самі дані. --- ## `shouldComponentUpdate()` - у класових компонентах Це метод життєвого циклу, який викликається **перед повторним рендером**: ```javascript class User extends React.Component { shouldComponentUpdate(nextProps, nextState) { // повернути false → React пропустить render() return nextProps.name !== this.props.name; } render() { console.log('рендер'); return <div>{this.props.name}</div>; } } ``` Якщо метод повертає: - `true` -> React викликає `render()` і оновлює компонент; - `false` -> React **пропускає рендер** і **не чіпає DOM**. --- ## `React.memo()` - у функціональних компонентах > Це **HOC (Higher-Order Component)**, який робить для функціональних компонентів **те саме**, > що `shouldComponentUpdate` робить для класових. ```javascript const User = React.memo(function User({ name }) { console.log('рендер'); return <div>{name}</div>; }); ``` За замовчуванням React.memo робить **поверхневе порівняння** пропсів. Якщо старі і нові пропси ідентичні (за `Object.is`), компонент **не буде перерендерений**. --- ## Тобто: | Компонент | Механізм | Контроль | |---|---|---| | Класовий | `shouldComponentUpdate(nextProps, nextState)` | Повертаєш `true` / `false` | | Функціональний | `React.memo(Component, areEqual?)` | Другий аргумент - функція порівняння пропсів | --- ## Кастомне порівняння в `React.memo` Якщо потрібно - можна явно вказати **кастомну логіку порівняння** (аналог ручного `shouldComponentUpdate`): ```javascript const User = React.memo( function User({ name, age }) { console.log('рендер'); return <div>{name} ({age})</div>; }, (prevProps, nextProps) => prevProps.age === nextProps.age // Якщо true → не оновлюємо ); ``` Тут функція `areEqual(prevProps, nextProps)` повертає: - `true` -> не оновлювати (аналог `shouldComponentUpdate = false`); - `false` -> оновлювати (аналог `shouldComponentUpdate = true`). --- ## Пряма відповідність логіки | Що робить | Класовий варіант | Функціональний варіант | |---|---|---| | Перевіряє, чи змінилися props | `shouldComponentUpdate()` | `React.memo()` | | Поверхневе порівняння за замовчуванням | Ні (тільки через `PureComponent`) | Так, вбудоване в `React.memo()` | | Кастомна логіка порівняння | `shouldComponentUpdate(nextProps, nextState)` | `(prevProps, nextProps) => boolean` | | Пропускає ререндер | `return false` | `areEqual() → true` | --- ## Приклад: еквівалентний код ### Класовий компонент: ```javascript class Button extends React.Component { shouldComponentUpdate(nextProps) { return nextProps.label !== this.props.label; } render() { console.log('render'); return <button>{this.props.label}</button>; } } ``` ### Функціональний компонент: ```javascript const Button = React.memo( ({ label }) => { console.log('render'); return <button>{label}</button>; }, (prev, next) => prev.label === next.label ); ``` Поведінка абсолютно однакова. --- ## У чому різниця | Параметр | `shouldComponentUpdate()` | `React.memo()` | |---|---|---| | Застосовується до | Класових компонентів | Функціональних компонентів | | Контроль | Всередині компонента | Ззовні, при обгортанні | | Порівняння state | Так (через `nextState`) | Ні (лише props) | | Можна перевизначити | Так | Так (через `areEqual`) | | За замовчуванням поверхневе порівняння | Ні (потрібен `PureComponent`) | Так | | Де писати | Всередині класу | Ззовні: `React.memo(Component)` | --- ## Приклад з оптимізацією Без оптимізації: ```javascript function Parent({ user }) { return <Child user={user} />; } function Child({ user }) { console.log('render'); return <div>{user.name}</div>; } ``` Щоразу при новому об'єкті `user` -> `Child` перерендерюється. З `React.memo()`: ```javascript const Child = React.memo(({ user }) => { console.log('render'); return <div>{user.name}</div>; }); ``` Тепер React порівняє старий і новий `user` -> якщо посилання те саме, `Child` **не оновиться**. --- ## Підсумок > `React.memo()` ≈ `shouldComponentUpdate()` > - обидва потрібні, щоб **запобігати зайвим ререндерам**, якщо вхідні дані (props) не змінилися. | Спільна ціль | Поведінка | |---|---| | Підвищення продуктивності | Пропуск ререндеру, якщо дані не змінилися | | Поверхневе порівняння за замовчуванням | Лише у `React.memo()` і `PureComponent` | | Гнучкість через кастомне порівняння | Є в обох |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.