Как работает React Navigation под капотом?

React Navigation — это библиотека для организации навигации в приложениях на React Native. Она позволяет реализовывать переходы между экранами, управление стеком экранов, табами, drawer-меню и другими видами маршрутизации. Несмотря на то, что API библиотеки выглядит декларативно и просто, её внутренняя архитектура довольно гибкая и сложная. В основе работы React Navigation лежит концепция навигационного контейнера, маршрутов, состояния навигации и обработчиков событий.

Навигационный контейнер

В React Navigation всё приложение оборачивается в компонент NavigationContainer. Он играет роль контекста и корневого уровня навигации, который управляет навигационным состоянием (navigation state), передаёт его в навигаторы и обрабатывает действия пользователя.

Когда происходит действие навигации (например, navigate, goBack), NavigationContainer:

  1. Получает действие (navigation action)

  2. Проверяет текущее навигационное состояние

  3. Вызывает соответствующий навигатор (например, Stack Navigator) для обновления состояния

  4. Обновляет внутреннее состояние (navigationState)

  5. Ререндерит приложение на основе нового состояния

Состояние навигации — это обычный JavaScript-объект, содержащий информацию о текущем маршруте, истории переходов, параметрах маршрутов и т. д.

Навигаторы

React Navigation использует разные типы навигаторов, каждый из которых реализует определённый алгоритм управления переходами:

  • createStackNavigator — стековая навигация (stack)

  • createBottomTabNavigator — навигация по вкладкам (tabs)

  • createDrawerNavigator — навигация через боковое меню (drawer)

  • createMaterialTopTabNavigator — табы сверху с поддержкой свайпов

Каждый навигатор — это обёртка над маршрутизатором (router) и экраном (screen). Внутри навигатор:

  • регистрирует все дочерние маршруты

  • хранит стек маршрутов или индекс текущего маршрута

  • реализует логику добавления, удаления и замены экранов

  • определяет, как отрисовываются экраны (например, с анимацией или без)

  • обрабатывает жесты (если включены)

Роутеры

Каждый навигатор опирается на собственный роутер — это чистая функция, которая определяет, как навигационное состояние должно изменяться в ответ на действие.

Например, стек-роутер получает текущее состояние и действие NAVIGATE, и возвращает новое состояние со стеком экранов, в котором появился новый маршрут.

Роутеры делают React Navigation детерминированной системой — состояние можно воспроизводить, сохранять, сериализовать и предсказывать.

Пример роутер-функции (упрощённо):

function stackRouter(state, action) {
switch (action.type) {
case 'NAVIGATE':
return {
...state,
routes: \[...state.routes, { name: action.payload.name }\],
index: state.index + 1,
};
case 'GO_BACK':
return {
...state,
routes: state.routes.slice(0, -1),
index: state.index - 1,
};
default:
return state;
}
}

Состояние навигации

Состояние навигации — это древовидная структура, в которой каждая вложенность представляет под-навигацию:

{
index: 1,
routes: \[
{
name: 'Home',
},
{
name: 'Profile',
state: {
index: 0,
routes: \[
{ name: 'Details' }
\]
}
}
\]
}

Такое состояние позволяет поддерживать вложенные навигаторы и управлять ими независимо.

Навигационные действия

React Navigation использует объектно-ориентированные навигационные действия:

  • navigate({ name: 'ScreenName', params })

  • goBack()

  • push(name)

  • pop()

  • reset(state)

  • replace(name)

Все они транслируются в действие (action), которое передаётся в роутер, изменяет состояние, и запускает обновление интерфейса.

Каждое действие — это обычный JavaScript-объект с типом и нагрузкой:

{
type: 'NAVIGATE',
payload: {
name: 'Profile',
params: { userId: 42 }
}
}

Хранилище состояния

Навигационное состояние может быть:

  • полностью контролируемым (controlled navigation)

  • неконтролируемым (internal state)

Контролируемый режим позволяет синхронизировать состояние навигации с Redux, MobX, локальным состоянием или persistent-хранилищами.

Можно настроить сериализацию и десериализацию навигационного состояния при помощи initialState, onStateChange, getStateFromPath.

Жизненный цикл экранов

Каждый экран проходит через несколько событий:

  • focus — экран активен

  • blur — экран покинут

  • beforeRemove — экран скоро удалится из стека

  • state — навигационное состояние изменилось

Эти события можно отслеживать через хук useFocusEffect, useNavigationEvents, addListener.

useFocusEffect(
useCallback(() => {
// экран в фокусе
return () => {
// экран потерял фокус
};
}, \[\])
);  

Жесты и анимации

React Navigation работает совместно с react-native-gesture-handler и react-native-reanimated для поддержки жестов (свайпов, перетаскиваний, касаний) и анимаций экранов. Например, свайп вправо в stack-навигации инициирует анимацию удаления верхнего экрана.

Stack-навигация использует Transitioner, который координирует анимации появления и скрытия экранов.

Можно настроить переходы, отключить их или заменить на кастомные:

options={{
animationEnabled: false,
gestureEnabled: true
}}

Вложенная навигация

React Navigation допускает вложенные навигаторы, каждый из которых управляет своим уровнем состояния. Это позволяет строить сложные структуры, такие как:

  • Стек в табе

  • Таб в drawer

  • Stack → Tabs → Stack → Modal

Вложенные навигаторы получают доступ к navigation объектам и могут выполнять действия, которые будут передаваться вверх по иерархии.

Интеграция с deep linking

React Navigation поддерживает интеграцию с URI-схемами и позволяет запускать приложение сразу с нужного экрана, распарсив ссылку. Это реализуется через linking-конфигурацию:

<NavigationContainer
linking={{
prefixes: \['myapp://'\],
config: {
screens: {
Home: 'home',
Profile: 'user/:id',
}
}
}}
/>

Рендеринг экранов

Каждый навигатор контролирует, какие экраны отображаются в зависимости от текущего состояния. Компоненты экранов не рендерятся, если они не активны, если не указана настройка detachInactiveScreens: false.

По умолчанию неактивные экраны не удаляются из памяти, а лишь «отключаются» визуально, что ускоряет возврат к ним.

Итоги архитектурной цепочки

  1. Пользователь вызывает navigation.navigate()

  2. NavigationContainer получает действие

  3. Соответствующий роутер рассчитывает новое состояние

  4. Обновляется navigationState

  5. Компоненты рендерятся согласно новому состоянию

  6. Навигатор управляет анимациями и жестами

  7. Экраны получают props.navigation и могут инициировать новые действия

React Navigation представляет собой фреймворк со слоистой архитектурой: поверх навигационных действий и состояния находятся абстракции навигаторов, роутеров и экранов, а под ними лежит связка JavaScript и нативных компонентов с управлением анимациями, жестами и маршрутизацией.