Оптимизация Реакт компонентов

Команда React.js прилагает все усилия для того, чтобы React работал как можно быстрее. Чтобы разработчики могли ускорить свои приложения, написанные на React, в него были добавлены следующие инструменты:

  • Pure Component
  • хуки жизненного цикла shouldComponentUpdate(){}
  • React.memo

Причина

В React каждому компоненту соответствует единица просмотра. Также у компонентов есть состояния. Когда из-за действий пользователя меняется значение состояния, компонент понимает, что нужна перерисовка. Компонент React может перерисовываться любое количество раз. В некоторых случаях это необходимо, но чаще всего без ререндера можно обойтись, тем более что он сильно замедляет работу приложения.

0

Если мы откроем консоль то увидим

unnesessary render

Компонент не должен перерисовываться, т.к состояние не изменилось. Значение счетчика «до­»­­ — 1, новое значение — тоже 1, следовательно обновлять DOM нет необходимости.

Избежать лишнего рендера в компонентах React поможет хук жизненного цикла shouldComponentUpdate.

React запускает метод shouldComponentUpdate в начале отрисовки компонента и получает от этого метода true/false.

shouldComponentUpdate принимает следующие аргументы:

  • nextProps: следующее значение props, которое получит компонент;
  • nextState: следующее значение state, которое получит компонент.

Теперь наш компонент может выглядеть так:

0

Теперь если мы откроем консоль то увидим только одно значение componentDidUpdate with shouldComponentUpdate при остальных нажатиях на кнопку shouldComponentUpdate будет возвращать false тем самым говорить нашему компоненту, что обновляться нет необходимости. Это происходит потому что мы добавили lifecycle shouldComponentUpdate в компонент Counter. Теперь значение count в объекте текущего состояния this.state.count сравнивается со значением count в объекте следующего состояния nextState.count. Если они равны ===, перерисовка не происходит и возвращается значение false. Если они не равны, возвращается значение true и для отображения нового значения запускается ререндер.

Pure Component

React.PureComponent похож на React.Component. Отличие заключается в том, что React.Component не реализует shouldComponentUpdate(), а React.PureComponent реализует его поверхностным сравнением пропсов и состояния.

0

Если вы откроете консоль то сможете убедиться, что появилась только одна запись componentDidUpdate with Pure Component.

note

Метод shouldComponentUpdate() базового класса React.PureComponent делает только поверхностное сравнение объектов. Если они содержат сложные структуры данных, это может привести к неправильной работе для более глубоких различий (то есть, различий, не выраженных на поверхности структуры). Наследуйте класс PureComponent только тогда, когда вы ожидаете использовать простые пропсы и состояние. Кроме того, метод shouldComponentUpdate() базового класса React.PureComponent пропускает обновление пропсов для всего поддерева компонентов. Убедитесь, что все дочерние компоненты также являются «чистыми».

Примечание
  • НЕ переопределяйте shouldComponentUpdate, если используете PureComponent. Используйте в таком случае Component!
  • НЕ пишите shouldComponentUpdate следующим образом:
shouldComponentUpdate(nextProps, nextState) {
return !JSON.stringify(nextProps) === !JSON.stringify(this.props) || !JSON.stringify(nextState) === !JSON.stringify(this.state);
}

React.memo

React.memo — это компонент высшего порядка. Принцип ее работы схож с принципом работы React.PureComponent:

  • помощь в управлении перерисовкой компонентов-функций. React.memo() для компонентов-классов — это React.PureComponent для компонентов-функций.
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
Важно

React.memo затрагивает только изменения пропсов. Если функциональный компонент обёрнут в React.memo и использует useState или useContext, он будет повторно рендериться при изменении состояния или контекста.

По умолчанию он только поверхностно сравнивает сложные объекты в объекте props. Если вы хотите контролировать сравнение, вы также можете предоставить пользовательскую функцию сравнения в качестве второго аргумента.

function MyComponent(props) {
/* рендер с использованием пропсов */
}
function areEqual(prevProps, nextProps) {
/*
возвращает true, если nextProps рендерит
тот же результат что и prevProps,
иначе возвращает false
*/
}
export default React.memo(MyComponent, areEqual);
Примечание

В отличие от метода shouldComponentUpdate() для классовых компонентов, функция areEqual возвращает true, если пропсы равны, и значение false, если пропсы не равны. Это обратные значения для shouldComponentUpdate.

Этот метод существует только для оптимизации производительности.Не полагайтесь на него, чтобы «предотвратить» рендеринг, так как это может привести к ошибкам.

Как работать с React.memo ?

0

Initial count 0

Почитать 📚

Edit this page on GitHub