Отрисовка и фиксация
Прежде чем ваши компоненты будут отображены на экране, их необходимо отрисовать React. Понимание этапов этого процесса поможет вам разобраться в том, как выполняется ваш код, и объяснить его поведение.
Вы узнаете
- Что означает отрисовка в React
- Когда и почему React отрисовывает компонент
- Этапы отображения компонента на экране
- Почему отрисовка не всегда приводит к обновлению DOM
Представьте, что ваши компоненты — это повара на кухне, собирающие вкусные блюда из ингредиентов. В этом сценарии React — это официант, который принимает заказы от клиентов и приносит им их. Этот процесс получения и предоставления пользовательского интерфейса состоит из трех этапов:
- Вызов отрисовки (передача заказа клиента на кухню)
- Отрисовка компонента (приготовление заказа на кухне)
- Фиксация в DOM (размещение заказа на столе)
Вызов Отрисовка Фиксация
Иллюстрация предоставлена Рэйчел Ли Наборс
Шаг 1: Вызов отрисовки
Существует две причины для отрисовки компонента:
- Это первичная отрисовка компонента.
- Состояние компонента (или одного из его предков) было обновлено.
Первичная отрисовка
При запуске приложения необходимо вызвать первичную отрисовку. Фреймворки и песочницы иногда скрывают этот код, но он выполняется путем вызова createRoot с целевым узлом DOM, а затем вызова его render метода с вашим компонентом:
import Image from './Image.js'; import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')) root.render(<Image />);
Попробуйте закомментировать вызов root.render() и вы увидите, как компонент исчезнет!
Повторная отрисовка при обновлении состояния
После первоначальной отрисовки компонента вы можете вызвать дальнейшие отрисовки, обновив его состояние с помощью функции set. Обновление состояния компонента автоматически добавляет в очередь отрисовку. (Вы можете представить это как ситуацию, когда гость в ресторане заказывает чай, десерт и многое другое после первого заказа, в зависимости от степени жажды или голода.)
Обновление состояния… …вызывает… …отрисовку!
Иллюстрация предоставлена Рэйчел Ли Наборс
Шаг 2: React отрисовывает ваши компоненты
После вызова отрисовки React обращается к вашим компонентам, чтобы определить, что отобразить на экране. «Отрисовка» — это обращение React к вашим компонентам.
- При первоначальной отрисовке React обратится к корневому компоненту.
- При последующих отрисовках React обратится к тому функциональному компоненту, чье обновление состояния вызвало отрисовку.
Этот процесс рекурсивный: если обновленный компонент возвращает другой компонент, React затем отрисует его, и если этот компонент также возвращает что-то, он отрисует это, и так далее. Процесс будет продолжаться до тех пор, пока не останется вложенных компонентов, и React не определит, что именно должно быть отображено на экране.
В следующем примере React будет вызывать Gallery() и Image() несколько раз:
export default function Gallery() { return ( <section> <h1>Inspiring Sculptures</h1> <Image /> <Image /> <Image /> </section> ); } function Image() { return ( <img src="https://i.imgur.com/ZF6s192.jpg" alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals" /> ); }
-
Во время первоначальной отрисовки React создаст узлы DOM для
<section>,<h1>, и трех<img>тегов. - Во время повторной отрисовки React рассчитает, какие из их свойств, если таковые имеются, изменились с момента предыдущей отрисовки. Он не будет ничего с этим делать до следующего шага — этапа фиксации.
Опасность
Отрисовка должна всегда быть чистым вычислением:
- Одинаковые входные данные, одинаковый выход. При одинаковых входных данных компонент должен всегда возвращать одинаковый JSX. (Если кто-то заказывает салат с помидорами, он не должен получить салат с луком!)
- Заниматься своими делами. Он не должен изменять какие-либо объекты или переменные, существовавшие до отрисовки. (Один заказ не должен менять заказ другого человека.)
В противном случае вы можете столкнуться с непонятными ошибками и непредсказуемым поведением по мере роста сложности вашего кода. При разработке в «Жестком режиме» React вызывает функцию каждого компонента дважды, что может помочь выявить ошибки, вызванные нечистыми функциями.
Подробное изучение
Оптимизация производительности
По умолчанию отрисовка всех компонентов, вложенных в обновленный компонент, не является оптимальной с точки зрения производительности, если обновленный компонент находится очень высоко в дереве. Если у вас возникнут проблемы с производительностью, существует несколько способов решения этой проблемы, описанных в разделе Производительность. Не оптимизируйте преждевременно!
Шаг 3: React фиксирует изменения в DOM
После отрисовки (вызова) ваших компонентов React внесет изменения в DOM.
-
При первоначальной отрисовке React использует API DOM
appendChild(), чтобы поместить все созданные узлы DOM на экран. - При повторных отрисовках React применит минимально необходимые операции (рассчитанные во время отрисовки!) для соответствия DOM последнему результату отрисовки.
React изменяет узлы DOM только в случае различий между отрисовками. Например, вот компонент, который повторно отрисовывается с разными свойствами, передаваемыми его родителем каждую секунду. Обратите внимание, как вы можете добавить текст в <input>, обновив его value, но текст не исчезает при повторной отрисовке компонента:
export default function Clock({ time }) { return ( <> <h1>{time}</h1> <input /> </> ); }
Это работает, потому что на этом последнем этапе React обновляет только содержимое <h1> новым time. Он видит, что <input> появляется в JSX в том же месте, что и в прошлый раз, поэтому React не трогает <input> — или его value!
Заключение: Отрисовка браузера
После завершения отрисовки и обновления DOM React браузер перерисует экран. Хотя этот процесс известен как «отрисовка браузера», мы будем называть его «перерисовкой», чтобы избежать путаницы в документации.
Иллюстрация предоставлена Рэйчел Ли Наборс
Резюме
- Любое обновление экрана в приложении React происходит в три этапа:
- Вызов
- Отрисовка
- Фиксация
- Вы можете использовать режим строгой проверки, чтобы найти ошибки в своих компонентах
- React не изменяет DOM, если результат отрисовки такой же, как и в прошлый раз
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/learn/render-and-commit