v19.2Latest

Рендер и фиксация

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

Вы узнаете
  • Что означает рендеринг в React
  • Когда и почему React рендерит компонент
  • Шаги, связанные с отображением компонента на экране
  • Почему рендеринг не всегда приводит к обновлению DOM

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

  1. Инициированиерендера (передача заказа гостя на кухню)
  2. Рендерингкомпонента (приготовление заказа на кухне)
  3. Фиксацияв DOM (размещение заказа на столе)
  1. React в роли официанта в ресторане, принимающий заказы от пользователей и доставляющий их на Компонентную Кухню.Инициирование
  2. Шеф-повар Card передаёт React свежий компонент Card.Рендеринг
  3. React доставляет компонент Card пользователю за его стол.Фиксация

Иллюстрации:Rachel Lee Nabors

Шаг 1: Инициирование рендера

Существует две причины для рендеринга компонента:

  1. Это первоначальный рендер компонента.
  2. Состояние компонента (или одного из его предков)было обновлено.

Первоначальный рендер

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

Попробуйте закомментировать вызовroot.render()и увидите, как компонент исчезнет!

Повторные рендеры при обновлении состояния

После того как компонент был первоначально отрендерен, вы можете инициировать дальнейшие рендеры, обновляя его состояние с помощьюфункции set.Обновление состояния вашего компонента автоматически ставит рендер в очередь. (Вы можете представить это как посетителя ресторана, который заказывает чай, десерт и всё что угодно после своего первого заказа, в зависимости от состояния его жажды или голода.)

  1. React в роли официанта в ресторане, подающий пользовательский интерфейс Card пользователю, представленному как посетитель с курсором вместо головы. Посетитель выражает желание получить розовую карточку, а не чёрную!Обновление состояния...
  2. React возвращается на Компонентную Кухню и говорит Шеф-повару Card, что ему нужна розовая карточка Card....инициирует...
  3. Шеф-повар Card передаёт React розовую карточку Card....рендер!

Иллюстрации:Rachel Lee Nabors

Шаг 2: React рендерит ваши компоненты

После того как вы инициировали рендер, React вызывает ваши компоненты, чтобы выяснить, что отображать на экране.«Рендеринг» — это вызов React'ом ваших компонентов.

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

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

В следующем примере React вызоветGallery() и Image()несколько раз:

  • При первоначальном рендерингеReactсоздаст DOM-узлыдля<section>,<h1>и трёх тегов<img>.
  • При повторном рендерингеReact вычислит, какие из их свойств, если таковые имеются, изменились с момента предыдущего рендеринга. Он не будет ничего делать с этой информацией до следующего шага — фазы фиксации.
Подводный камень

Рендеринг всегда должен бытьчистым вычислением:

  • Одинаковые входные данные — одинаковый результат.При одинаковых входных данных компонент всегда должен возвращать одинаковый JSX. (Когда кто-то заказывает салат с помидорами, он не должен получить салат с луком!)
  • Он занимается своим делом.Он не должен изменять никакие объекты или переменные, существовавшие до рендеринга. (Один заказ не должен изменять чужой заказ.)

В противном случае по мере усложнения кодовой базы могут возникать запутанные ошибки и непредсказуемое поведение. При разработке в «Строгом режиме» React вызывает функцию каждого компонента дважды, что может помочь выявить ошибки, вызванные нечистыми функциями.

Deep Dive
Оптимизация производительности

Шаг 3: React фиксирует изменения в DOM

После рендеринга (вызова) ваших компонентов React изменит DOM.

  • При первоначальном рендерингеReact использует DOM APIappendChild(), чтобы разместить на экране все созданные DOM-узлы.
  • При повторных рендерингахReact применит минимально необходимые операции (вычисленные во время рендеринга!), чтобы привести DOM в соответствие с последним результатом рендеринга.

React изменяет DOM-узлы только в случае различий между рендерами.Например, вот компонент, который перерисовывается с разными пропсами, передаваемыми от родителя, каждую секунду. Обратите внимание, что вы можете добавить текст в<input>, обновив егоvalue, но текст не исчезает при повторном рендеринге компонента:

Это работает, потому что на последнем шаге React обновляет только содержимое<h1>новым значениемtime. Он видит, что<input>появляется в JSX в том же месте, что и в прошлый раз, поэтому React не трогает<input>— или егоvalue!

Эпилог: Отрисовка браузером

После завершения рендеринга и обновления DOM React'ом браузер перерисует экран. Хотя этот процесс известен как «рендеринг браузера», мы будем называть его «отрисовкой», чтобы избежать путаницы в документации.

Браузер рисует 'натюрморт с карточным элементом'.

Иллюстрация:Рэйчел Ли Наборс

Итоги

  • Любое обновление экрана в React-приложении происходит в три этапа:
    1. Триггер
    2. Рендер
    3. Фиксация
  • Вы можете использовать Строгий режим для поиска ошибок в ваших компонентах
  • React не трогает DOM, если результат рендеринга совпадает с предыдущим