Что происходит после создания work tree и current tree в React
Что проверяют
Знаете ли вы внутреннее устройство согласования в React и понимаете ли разницу между фазой рендера и фазой коммита. Вопрос уровня выше среднего: по ответу видно, читали ли вы, как устроен Fiber, или знаете только про «виртуальный DOM, который быстрее».
Как отвечать
current это дерево узлов, которое уже отражено на экране. При обновлении React строит второе дерево, workInProgress, переиспользуя узлы через ссылку alternate. Это двойная буферизация: два дерева живут одновременно, объекты узлов не пересоздаются с нуля.
Дальше происходит следующее:
- фаза рендера. React обходит дерево сверху вниз, сравнивает новый элемент со старым узлом по типу и ключу и решает, переиспользовать узел или создать новый, а на обратном пути собирает пометки о том, что нужно сделать с DOM. Фаза прерываемая: работу можно отложить, начать заново или выбросить, поэтому побочных действий в ней быть не должно;
- фаза коммита. Она синхронная и не прерывается: применяются мутации DOM, затем указатель
currentпереключается на построенное дерево, и оно становится текущим. Вокруг переключения вызываются очистки и телаuseLayoutEffect, до того как браузер нарисует кадр; - пассивные эффекты
useEffectвызываются уже после отрисовки.
Где спотыкаются
Говорят, что React «обновляет текущее дерево». Он его не правит, он достраивает второе и переключает указатель. Именно поэтому незавершённую работу можно выбросить, и на экране не останется следов.
Считают, что сравнение идёт с реальным DOM. Сравниваются описания узлов, до DOM дело доходит только в коммите. Оттуда же и правило чистоты: в режиме разработки рендер могут выполнить дважды, и код с побочным эффектом отработает дважды.
Путают роль ключей. Ключ решает, считать узел тем же самым или создать новый. Индекс массива в списке, который меняется, заставляет React переиспользовать чужой узел, и состояние вместе с фокусом уезжает к соседней строке.