Путешествие к внутреннему устройству компонентов React.

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

Подумайте немного о том, что делает компонент React… Основываясь на том, что мы рассмотрели до сих пор, в одном предложении: он описывает, что отображать. Мы уже знаем, что для этой цели он использует метод render (). Однако наличие только метода render () не всегда может соответствовать нашим требованиям. Что, если мы хотим что-то сделать до или после того, как компонент будет отрисован или смонтирован? Что, если мы хотим избежать повторного рендеринга?

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

По сути, все методы жизненного цикла компонента React можно разделить на четыре этапа: инициализация, монтирование, обновление и размонтирование. Давайте подробнее рассмотрим каждый из них.

Инициализация

На этапе инициализации мы определяем значения по умолчанию и начальные значения для this.props и this.state, реализуя getDefaultProps () и getInitialState () соответственно.

Метод getDefaultProps () вызывается один раз и кэшируется - используется во всех экземплярах - при создании класса до создания любого экземпляра компонента. , поэтому здесь мы не можем полагаться на this.props. Этот метод возвращает объект, значения свойств которого будут установлены в this.props, если этот параметр не указан родительским компонентом.

Метод getInitialState () также вызывается один раз, непосредственно перед этапом монтирования. Возвращаемое значение этого метода будет использоваться как начальное значение this.state и должно быть объектом.

Теперь мы можем продемонстрировать ранее представленный, реализуя компонент, который показывает значение, которое можно увеличивать и уменьшать в интерактивном режиме, в основном это счетчик, обрабатываемый кнопками «+» и «-».

Мы настроили с помощью getDefaultProps () свойство «title», которое, если не указано, имеет значение по умолчанию. Также мы устанавливаем начальное состояние компонента «{count: 0}» через getInitialState (). Если мы запустим этот код и посмотрим на вывод консоли, вы увидите порядок выполнения методов:

Теперь мы добавим к компоненту Counter возможность установки начального значения this.state.count и значения шага увеличения / уменьшения, но также мы будем предоставить разумные значения по умолчанию.

Примечание:

Здесь мы используем частичное приложение через Function.prototype.bind, чтобы избавиться от дублированного кода.

Теперь у нас есть более индивидуальный компонент !!!

Монтаж

Монтирование - это процесс, который происходит, когда компонент вставляется в DOM. На этом этапе есть два метода, с которыми мы можем подключиться: componentWillMount () и componentDidMount ().

Метод componentWillMount () вызывается первым на этом этапе. Он вызывается один раз и сразу перед первоначальной отрисовкой, то есть до того, как React вставит компонент в DOM. Очень важно отметить, что вызов this.setState () в этом методе не приведет к повторной визуализации. Если мы добавим следующий код в компонент Counter, мы увидим, что метод вызывается после getInitialState () и до render ( ).

getInitialState: function() {...},
componentWillMount: function() {
    console.log('componentWillMount');
},
...

componentDidMount () - второй, вызываемый на этом этапе, всего один раз и сразу после того, как React вставляет компонент в DOM . Теперь обновленная модель DOM доступна для доступа, а это означает, что этот метод является лучшим местом для инициализации других библиотек Javascript, которым необходим доступ к модели DOM и для операций выборки данных.

Предположим, мы хотим инициализировать компонент Counter данными, полученными из API. Мы могли бы получить данные напрямую в методе Counter componentDidMount (), но похоже, что это слишком большая ответственность для этого компонента. Вместо этого мы можем сделать это в компоненте контейнера следующим образом:

Примечание:

Axios - это HTTP -клиент на основе обещаний для браузера и Node.js.

Обновление

Существуют также методы, которые позволяют нам выполнять код, связанный с обновлением состояния или свойств компонента. Эти методы являются частью фазы обновления и вызываются в следующем порядке:

  1. При получении нового реквизита от родителя:

2. Когда состояние изменяется с помощью this.setState ():

На этом этапе компонент React уже вставлен в DOM. Таким образом, эти методы не вызываются для первого render ().

Первый - componentWillReceiveProps (), вызываемый, когда компонент получает новые свойства. Мы можем использовать этот метод как возможность отреагировать на переход свойства до вызова метода render (). Вызов this.setState () в этой функции не вызовет дополнительной повторной визуализации, и мы можем получить доступ к старым реквизитам через this.props . Например, в компоненте Counter, если мы хотим обновлять состояние всякий раз, когда родительский элемент передает свойство «initialCount», мы можем сделать это следующим образом:

...
componentWillReceiveProps: function(newProps) {
    this.setState({count: newProps.initialCount});
},
...

Метод shouldComponentUpdate () позволяет нам решить, должно ли состояние следующего компонента запускать повторную визуализацию или нет. Этот метод возвращает логическое значение, которое по умолчанию истинно. Но мы можем вернуть false, и следующие методы не будут вызваны:

  • componentWillUpdate ()
  • render ()
  • componentDidUpdate ()

Мы можем использовать метод shouldComponentUpdate (), если производительность является узким местом. Особенно с десятками или сотнями компонентов, где повторный рендеринг стоит особенно дорого. Для наглядности рассмотрим пример:

В этом надуманном примере всякий раз, когда родитель передает свойство «text» в TextComponent и равно текущему свойству «text», повторно -render не будет.

Метод componentWillUpdate () вызывается непосредственно перед отрисовкой, когда принимаются новые свойства или состояние. Мы можем использовать это как возможность выполнить подготовку до того, как произойдет обновление, однако не разрешено использовать this.setState ().

...
componentWillUpdate: function(nextProps, nextState) {
    console.log('componentWillUpdate', nextProps, nextState);
},
...

Метод componentDidUpdate () вызывается сразу после того, как React обновляет DOM. Мы можем использовать этот метод для взаимодействия с обновленной DOM или для выполнения любых действий после рендеринга. Этот метод получает два аргумента:

  1. prevProps: предыдущий объект свойств
  2. prevState: предыдущий объект состояния

Распространенный случай для этого метода - это когда мы используем стороннюю библиотеку, которой требуется отрисованная DOM для выполнения своей работы - например, плагин jQuery -. Мы инициализируем библиотеку в первый раз в методе componentDidMount (), но после некоторого изменения свойства или состояния, которое запускает обновление DOM, нам необходимо обновить также стороннюю библиотеку. чтобы наш интерфейс был единообразным. Это необходимо сделать с помощью метода componentDidUpdate (). Чтобы проиллюстрировать это, давайте посмотрим, как сделать компонент-оболочку React для библиотеки Select2:

Размонтирование

На этом этапе React предоставляет нам только один метод:

  • componentWillUnmount ()

Он вызывается непосредственно перед отключением компонента от DOM. Мы можем использовать его для выполнения любой очистки, которая может нам понадобиться, например, аннулирования таймеров или очистки любых элементов DOM, которые были созданы в componentDidMount () / componentDidUpdate (). Например, в компоненте Select2 мы могли бы использовать его следующим образом:

...
componetWillUnmount: function(){
   $(this._ref).select2('destroy');
},
...

Выводы

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

Надеюсь, этот пост окажется для вас полезным. Ваше здоровье.