Как работает React Navigation под капотом?
React Navigation — это библиотека для организации навигации в приложениях на React Native. Она позволяет реализовывать переходы между экранами, управление стеком экранов, табами, drawer-меню и другими видами маршрутизации. Несмотря на то, что API библиотеки выглядит декларативно и просто, её внутренняя архитектура довольно гибкая и сложная. В основе работы React Navigation лежит концепция навигационного контейнера, маршрутов, состояния навигации и обработчиков событий.
Навигационный контейнер
В React Navigation всё приложение оборачивается в компонент NavigationContainer. Он играет роль контекста и корневого уровня навигации, который управляет навигационным состоянием (navigation state), передаёт его в навигаторы и обрабатывает действия пользователя.
Когда происходит действие навигации (например, navigate, goBack), NavigationContainer:
-
Получает действие (navigation action)
-
Проверяет текущее навигационное состояние
-
Вызывает соответствующий навигатор (например, Stack Navigator) для обновления состояния
-
Обновляет внутреннее состояние (navigationState)
-
Ререндерит приложение на основе нового состояния
Состояние навигации — это обычный 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.
По умолчанию неактивные экраны не удаляются из памяти, а лишь «отключаются» визуально, что ускоряет возврат к ним.
Итоги архитектурной цепочки
-
Пользователь вызывает navigation.navigate()
-
NavigationContainer получает действие
-
Соответствующий роутер рассчитывает новое состояние
-
Обновляется navigationState
-
Компоненты рендерятся согласно новому состоянию
-
Навигатор управляет анимациями и жестами
-
Экраны получают props.navigation и могут инициировать новые действия
React Navigation представляет собой фреймворк со слоистой архитектурой: поверх навигационных действий и состояния находятся абстракции навигаторов, роутеров и экранов, а под ними лежит связка JavaScript и нативных компонентов с управлением анимациями, жестами и маршрутизацией.