shouldComponentUpdate, PureComponent, memo

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

Вот пример, файл src/Profile/Profile.jsx

import React from 'react';
import s from './Profile.module.css';
import ProfileInfo from './ProfileInfo/ProfileInfo';
import MyPostsContainer from './MyPosts/MyPostsContainer';

const Profile = (props) => {
   return  (
      <div>
        <ProfileInfo profile={props.profile} status={props.status} updateStatus={props.updateStatus} />
        <MyPostsContainer />
      </div>
    )
}

export default Profile;

Здесь мы отрисовываем компоненту Profile, которая обернута в контейнерную компоненту ProfileContainer (здесь это не показано) и обновляется при изменении аж 4 свойств, согласно mapStateToProps.

Но внутри Profile есть еще одна компонента – MyPostsContainer, что видно в 10 строке. В итоге она получается тоже перерисовывается каждий раз, когда перерисовывается и сама Profile, но каждый раз возвращает одно и то же, ведь в нее приходит все то же самое.

Нам нужно сообщить MyPostsContainer, чтобы она не перерисовывалась.

shouldComponentUpdate

В классовых компонентах для этого есть метод shouldComponentUpdate. Вот таким образом можно сказать нашей компоненте, чтобы она отрисовалась только один раз:

class MyPosts extends React.Component {

  shouldComponentUpdate(nextProps, nextState) {
    return false;
  }

  render() {
.......

Конкретно в такмо виде shouldComponentUpdate не используется. Вместо возвращения false там должно быть какое-то сравнение приходящих с пропсов или стейта значений с новыми аналогичным значениями. Например:

shouldComponentUpdate(nextProps, nextState) {
   return NextProps.value != this.props.value || NextState.value != this.state.value;
 }

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

PureComponent

Метод PureComponent делает по сути то же, что и shouldComponentUpdate, но он позволяет не не описывать поведение вручную, т.е. не указывать при изменении чего должен происходить рендеринг.

React.PureComponent применяется вместо базового React.Component, который обычно прописывается в классовых компонентах. Они очень похожи, разница только в том, что React.PureComponent не может реализовывать shouldComponentUpdate, а вместо этого сразу по умолчанию делает поверхносное сравнение пропсов и стейта.

Если компонента всегда рендерит одинаковый результат при одних и тех же пропсах и стейте, для повышения производительности можно использовать React.PureComponent. Для этого Component просто заменяется на PureComponent в месте импорта и в объявлении класса:

  • было:
    import React, {Component} from 'react';
    ...
    class MyPosts extends React.Component {
    ....
  • cтало:
    import React, {PureComponent} from 'react';
    ...
    class MyPosts extends React.PureComponent {
    ...

     

memo

React.memo – это HOC, который играет аналогичную роль метода React.PureComponent, только в функциональных компонентах. То есть этот HOC тоже применяется для того, чтобы компонента лишний раз не перерисовывалась.

Вот пример:

const MyPosts = React.memo(props => {
  ...


  return  (
  ...
    )
}); //вот здесь закрывающая скобка

Очень вероятно, что сейчас memo работает по умолчанию, как показывают отзывы и небольшие эксперименты.

2 ответа к «shouldComponentUpdate, PureComponent, memo»

  1. Очень вероятно мемо не работает по умолчанию и некогда не будет работать по умолчанию, не вводите в заблуждение людей.

    1. этой статье несколько лет, писал ее, когда я еще начинал изучать фронтенд. Это просто мои заметки, и верить здесь ничему однозначно нельзя)) На тот момент мне так казалось либо так говорилось в источнике (ролике на ютубе, где я брал материал).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *