Как работает виртуальный DOM в React Native?
Виртуальный DOM (Virtual DOM, или VDOM) в React Native работает по тем же принципам, что и в веб-версии React, но с ключевыми отличиями в реализации из-за отсутствия настоящего DOM в React Native. Вместо HTML-элементов и браузерного DOM, React Native использует виртуальное представление интерфейса, которое маппится на нативные компоненты платформы — такие как UIView в iOS или View в Android.
В основе React Native лежит идея декларативного программирования интерфейсов: разработчик описывает, что должно быть показано на экране, а React (в связке с виртуальным деревом) определяет, как это оптимально обновить.
Что такое Virtual DOM
Виртуальный DOM — это абстрактное дерево компонентов, хранящееся в памяти. Оно представляет собой объектную модель пользовательского интерфейса, созданную средствами JavaScript. Каждый компонент React возвращает JSX — описание интерфейса, которое преобразуется во внутреннюю структуру данных (ReactElement). Эта структура образует виртуальное дерево компонентов (VDOM), используемое React'ом для сравнения изменений.
Как работает Virtual DOM в React Native
Шаг 1: Рендеринг компонента
При первом рендере компонента:
-
React вызывает компонент-функцию или render() метода класса.
-
JSX преобразуется в JavaScript-объекты (React.createElement).
-
Эти объекты формируют виртуальное дерево (Virtual DOM).
-
React Native "переводит" это дерево в нативные представления: Text, View, Image и др.
Шаг 2: Сравнение деревьев (диффинг)
При изменении состояния (state) или свойств (props):
-
Компонент ререндерится и создаёт новое виртуальное дерево.
-
React сравнивает новое дерево с предыдущим (этот процесс называется diffing).
-
Определяются минимальные изменения, которые нужно внести в реальный интерфейс.
-
Эти изменения транслируются через bridge (или JSI/Fabric) в нативные UI-компоненты.
Шаг 3: Применение изменений
-
React вызывает соответствующие команды (например, обновить текст, изменить стиль, переместить элемент).
-
Эти команды проходят через UIManager, Fabric или bridge и применяются к нативным представлениям Android/iOS.
-
UI обновляется без полной перерисовки — только то, что действительно изменилось.
Пример: что происходит при обновлении
const App = () => {
const \[count, setCount\] = useState(0);
return (
<View>
<Text>Счётчик: {count}</Text>
<Button title="Увеличить" onPress={() => setCount(count + 1)} />
</View>
);
};
-
При первом запуске count = 0, создаётся виртуальное дерево:
- View → Text("Счётчик: 0") + Button(...)
-
При нажатии кнопки вызывается setCount(1)
-
React вызывает App(), генерирует новое дерево:
- View → Text("Счётчик: 1") + Button(...)
-
React сравнивает старое и новое дерево и видит, что изменился **только текст
** - Через bridge или JSI React Native обновляет только этот текст, не трогая весь View или Button
Отличие от браузерного DOM
Функция / аспект | React (веб) | React Native |
---|---|---|
Реальный DOM | Браузерный DOM | Нативные компоненты iOS/Android |
--- | --- | --- |
Элемент div, span, h1 | HTML DOM-элементы | View, Text, Image и пр. |
--- | --- | --- |
Обновления | DOM-операции через браузерный API | Команды в UIManager через bridge |
--- | --- | --- |
Цель Virtual DOM | Минимизировать перерисовки DOM | Минимизировать bridge и UI-апдейты |
--- | --- | --- |
Компоненты, Virtual DOM и Shadow Tree
React Native не работает напрямую с DOM. Вместо этого:
- Компоненты React описывают UI на уровне **Virtual DOM
** -
React Native транслирует VDOM в Shadow Tree (внутреннее представление компонентов, которое учитывает стили и позиционирование с помощью Yoga)
-
Затем Shadow Tree преобразуется в native views (например, UIView, TextView и т.д.)
Yoga — это движок расчёта макета (layout engine), разработанный Facebook, реализующий Flexbox для React Native. Он принимает размеры и стили компонентов из Shadow Tree и определяет точные координаты и размеры для отрисовки.
Обновление UI — важные этапы
-
**Реактивность
**- Любое изменение props или state вызывает ререндер компонента.
-
**Реконструкция VDOM
**- Новый React Element создаётся и сравнивается со старым.
-
**Diffing
**- React определяет, какие узлы изменились.
-
**Сериализация
**- Только изменённые части сериализуются и передаются через bridge (или JSI).
-
**Команды обновления
**- Native UI получает инструкции (например, обновить текст, применить стиль, изменить позицию).
-
**Отрисовка
**- Обновления применяются в нативной среде через платформенные виджеты (например, TextView, UIView и др.)
Оптимизация производительности VDOM в React Native
-
Мемоизация компонентов (React.memo, useMemo, useCallback)
-
**Оптимизированный FlatList/SectionList
**- Эти компоненты используют windowing (отрисовка только видимых элементов)
-
**Не мутировать объекты/массивы в props
**- Передавать новые ссылки, если содержимое изменилось
-
**Избегать лишних ререндеров
**- Использовать shouldComponentUpdate, React.memo или useEffect с правильными зависимостями
-
**Использовать key в списках
**- Для оптимального диффинга при изменении элементов
Как Virtual DOM связан с bridge
-
Virtual DOM работает внутри JS-движка (например, Hermes или JavaScriptCore).
-
После сравнения виртуальных деревьев React определяет diff (разницу).
-
Эта разница передаётся через bridge в нативную часть, где UI обновляется.
-
Bridge может стать узким местом (bottleneck), особенно при большом числе обновлений.
Чтобы уменьшить нагрузку на bridge:
-
React Native внедряет новую архитектуру (Fabric + JSI)
-
Fabric устраняет необходимость в сериализации: обновления передаются напрямую
-
Улучшается производительность и отзывчивость интерфейса
Новый рендерер: Fabric и влияние на Virtual DOM
Fabric — это новый UI-рендерер React Native. Он всё ещё использует Virtual DOM, но меняет архитектуру взаимодействия с нативным UI:
-
Вместо bridge используется JSI (JavaScript Interface)
-
Снижается задержка между JS и нативным кодом
-
Упрощён жизненный цикл компонентов
-
Улучшена поддержка синхронных обновлений (например, при анимациях)
С Fabric Virtual DOM становится ближе к нативной реализации, позволяя производить рендеринг быстрее и с меньшей стоимостью.
Virtual DOM в React Native — это механизм, который обеспечивает высокую производительность и эффективную синхронизацию пользовательского интерфейса между JavaScript-кодом и нативными компонентами. Он позволяет React Native-приложениям быть отзывчивыми и масштабируемыми, минимизируя количество реальных обновлений интерфейса за счёт умного сравнения и применения только необходимых изменений.