React shouldComponentUpdate демістифікований

Під час розробки в React ви коли-небудь замислювались, коли і чому запускається метод render () компонента? Або коли використовувати менш очевидні методи життєвого циклу слідComponentUpdate ()?

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

Все зводиться до того, як React працює під капотом. Великою обіцянкою React є те, що вона швидко блимає при отриманні елементів на сторінці.

Для цього React зберігає в пам'яті дві версії DOM:

  • версія DOM, що відображається на даний момент
  • відображатиметься наступна версія DOM

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

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

Це дуже хороший шаблон. Якщо придивитися уважніше, це означає, що будь-яка взаємодія користувача з поданням вплине на сам контейнер і спричинить візуалізацію його та всіх його дочірніх елементів. Скажімо, у вас є список елементів із вишуканим відображенням тексту, зображення та кнопкою подобання жовтої зірки "Додати до обраного". Мінімальною моделлю для елемента списку може бути:

product = { imageUrl: '...', title: '...', isFavourite: false }

Список обраних може походити з іншого джерела даних. Незалежно від того, ваша організація компонентів виглядає приблизно так:

Обробник викликається за клацанням користувача і зберігає сторону інформаційного сервера (або зберігається в магазині чи будь-якому іншому) і викликає зміну в this.props.elements.

Результат одного клацання викликає візуалізацію контейнера та всіх рядків у списку лише для оновлення одного прапорця.

Ось тут повинен увійти в систему shouldComponentUpdate (). Ви можете сказати React не відображати рядки, які не потребують використання цього методу.

class ListItem extends Component { shouldComponentUpdate(nextProps, nextState) { return nextProps.isFavourite != this.props.isFavourite; } ... }

Ось конкретний випадок: у проекті програми на ринку ми мали уявлення про управління продуктами для продавців. Список мав шаблон "завантажувати більше, коли користувач прокручує вниз", а також вбудовані елементи "показувати / приховувати" для встановлення видимості кожного товару. Все було добре, коли продавці керували на своїй інформаційній панелі <100 продуктами. Потім даний продавець почав вводити та рекламувати більше 300 товарів ...

До оновлення користувацького інтерфейсу після того, як користувач натиснув піктограму «увімкнути / вимкнути», було відставання ~ 600 мс. Відставання було точно видно кінцевому користувачеві. Використовуючи профайлер Chrome, ми побачили, що React знадобився ~ 2 мс, щоб відтворити один рядок. Рази 300 ... ми добирались до 600 мс. Ми додали перевірки shouldComponentUpdate () на належні умови. Час візуалізації після натискання користувачем менше 10 мс ...

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

Попередження для користувачів Redux

Описана вище проблема може траплятися частіше, якщо ви використовуєте Redux і повторно вибираєте (або подібні бібліотеки конвеєрів дій на основі магазину).

За допомогою Redux та повторного вибору ви надсилаєте дії до магазину, і ви підключаєте слухачі для зберігання змін, вони ж селектори. Селектори доступні у всьому світі в програмі, а у великій програмі багатьом компонентам досить легко зіставити ті самі селектори. Зміни в магазині можуть спричинити зміни реквізиту, а отже, відтворення, які абсолютно не стосуються деяких компонентів.

Ось заплутана порада: не використовуйте shouldComponentUpdate () для запобігання відтворення в таких випадках. Логіка всередині shouldComponentUpdate повинна розглядати лише те, що стосується компонента. Він ніколи не повинен передбачати контексти, в яких використовується компонент. Причина в тому, що ваш код швидко стане неможливим.

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

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

Дякуємо за читання! Якщо вам сподобалось, натисніть кнопку плескати нижче. Це допомагає іншим людям побачити історію.