День 6
Nikita Nikler
11 декабря 2024, 10:12

Решил немного углубиться в структуру объекта Fiber. Эти знания будут нужны для понимания работы алгоритмов React.

Первое поле ,которое нас встречает в типе Fiber исходного кода реакт - tag. Оно типизировано типом WorkTag и представляет собой перечисление числовых литералов от 0 до 29.

export type WorkTag = 0 | 1 | ... | 28 | 29;

Для каждого числа из перечисления существует константа со значением соответствующего числового литерала. Например:

export const FunctionComponent = 0;

Прежде ,чем попытаться дать определение этому полю ,посмотрим на другие константы ,которое оно может принимать:

  • FunctionComponent (0) - представляет функциональный компонент
  • ClassComponent (1) - представляет классовый компонент
  • HostRoot (3) - представляет корневой узел приложение ,то что создается через React.createRoot(). Является верхушкой дерева Fiber
  • HostComponent (5) - представляет обычный DOM-элемент
  • HostText (6) - представляет текстовый узел DOM
  • Fragment (7) - представляет фрагмент React (<></> или React.Fragment)
  • MemoComponent (14) - представляет функциональный компонент ,обернутый в memo
  • LazyComponent (16) - представляет компонент ,загружаемый асинхронно
  • и т.д. прочие теги пока что не очень интересны

Здесь можно заметить ,что Fiber хранит не тип ReactNode ,с которым он непосредственно связывается ,а способ создания этого ReactNode. Эту информацию он извлекает непосредственно из объекта ReactNode. Учитывая ,что ReactNode является типом-перечислением других типов ,свойства могут анализироваться разные для каждого типа.

Рассмотрим для простоты тип ReactElement ,который возвращается функциональными компонентами или методом render классовых. Он также может представляться элементом DOM ,созданным через React.createElement (или JSX-разметкой ,которая через babel все равно превратится в createElement). Нас будут интересовать 2 поля - $$typeof и type.

Сперва React определит ,что узел является ReactElement ,проверив $$typeof ,ведь для него он будет равен значению Symbol(react.element). Это позволяет React сразу же классифицировать ноду и понять ,как ее обрабатывать дальше.

Затем он посмотрит на поле type ,которое в случае ,если:

  • компонент функциональный - содержит ссылку на функцию (определение компонента)
  • компонент классовый - содержит ссылку на функцию-конструктор компонента
  • DOM-компонент - содержит строку с названием тега

Но тут загвоздка. И Function и Class представляют собой тип function в рантайме javascript. Как React их различает? Все довольно просто ,у функции-конструктора есть prototype ,хранящий отличительные методы ,характеризующие его как класс компонента. Например ,prototype.render ,на который и ориентируется React при проверке.

Разобрались с тем ,как это поле заполняется. Кстати заполняется оно при создания нового Fiber - в процессе первичного рендеринга или на этапе реконсиляции при цикле обновлений ,если это требуется. Далее рассмотрим ,какую роль он играет в механизмах React?

На основе значения tag React выбирает подходящий алгоритм для работы с данным Fiber для дальнейшего обновления DOM. При анализе изменений ,React может сравнить tag и сразу же понять ,что например при его отличии от предыдущей версии нужно создать новый Fiber ,и анализировать другие свойства уже нет смысла ,тем самым сократив кол-во всевозможных проверок до одной и оптимизировать цикл.

Такая ситуация может произойти в результате изменения структуры элементов ,например ,при работе со списками или условным отображением. Если вдруг после рендеринга на позиции компонента <A /> вдруг встал элемент <div /> ,то именно такая ситуация и произойдет ,тк это ноды разного типа. Однако ,если для A указать key ,то он корректно сопаставится с Fiber и не будет перемонтирован. То есть key - это еще одно свойство ,на которое смотрит React при сравнении и учитывает это. Более детально key я разберу когда-нибудь потом ,однако сразу замечу ,что в структуре объекта Fiber это свойство также присутствует.

Для tag MemoComponent React ,например также пропустит ряд проверок ,речь идет о компонентах ,обернутых в memo. Это тоже важная часть оптимизации ,которую я рассмотрю когда-нибудь позже.

Нравится? Расскажите друзьям!
Комментировать
Перейти к записи в ленте
Цель

Вы тоже можете
опубликовать свою
цель здесь

Мы поможем вам ее достичь!

310 000

единомышленников

инструменты

для увлекательного достижения

Присоединиться
Регистрация

Регистрация

Уже зарегистрированы?
Быстрая регистрация через соцсети
Вход на сайт

Входите.
Открыто.

Еще не зарегистрированы?
 
Войти через соцсети
Забыли пароль?