Как выстроить архитектуру крупного приложения на React Native?
Построение архитектуры крупного приложения на React Native требует системного подхода к организации кода, разделению ответственности, масштабируемости, производительности и удобству поддержки. Нельзя опираться только на шаблон App.js — важно заранее продумать структуру директорий, модели данных, управление состоянием, бизнес-логику, работу с API, кэширование, навигацию, переиспользуемые компоненты и подход к тестированию.
Структура директорий
Один из вариантов модульной архитектуры (Feature-Sliced или Domain Driven Design-подобной):
/src
/app
navigation/
theme/
store/
config/
constants/
/features
/auth
components/
screens/
services/
hooks/
slices/
/profile
...
/entities
/user
model/
types/
services/
/shared
/ui
/hooks
/utils
/components
/api
-
app/ — инициализация и глобальные зависимости
-
features/ — пользовательские функции (регистрация, авторизация, загрузка постов)
-
entities/ — абстракции домена (User, Post), без конкретной бизнес-логики
-
shared/ — переиспользуемые элементы
-
Каждый слой можно изолировать и переиспользовать
Навигация
Использование react-navigation с разделением по типам навигации:
NavigationContainer
└── RootNavigator
├── AuthStack
│ └── LoginScreen
└── MainStack
├── BottomTabs
└── Screens
-
Использовать вложенные навигаторы (stack внутри tabs, tabs внутри drawer)
-
Сохранение навигации в navigation/ (например, index.ts, routes.ts, linking.ts)
-
Конфигурация экранов по ролям или модулям
Состояние (State Management)
В крупных приложениях важно чётко разграничить:
-
Локальное состояние (useState, useReducer)
-
Состояние компонента (form, modal open)
-
Глобальное состояние (пользователь, токен, настройки)
Выбор инструментов:
-
**Redux Toolkit + RTK Query
**-
Удобно масштабируется
-
Инкапсуляция API-логики и кэширования
-
Поддержка middleware
-
createSlice, createAsyncThunk
-
-
**Zustand
**-
Минималистичная альтернатива Redux
-
Подходит для глобального состояния
-
-
**React Context
**- Только для небольшого глобального состояния (например, тема, язык)
-
Jotai, Recoil — альтернатива с атомарной структурой данных
Работа с API
Использование слоя абстракции для сетевых запросов:
-
axios с интерсепторами
-
fetch + обёртка с логами и авторизацией
-
RTK Query или React Query для кэширования, автоматических повторов, фетчинга
Пример: src/shared/api/userApi.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const userApi = createApi({
reducerPath: 'userApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (builder) => ({
getProfile: builder.query<User, void>({
query: () => 'profile',
}),
}),
});
Стили и тема
Хранение темы в app/theme/:
export const theme = {
colors: {
primary: '#4A90E2',
background: '#fff',
text: '#222',
},
spacing: {
sm: 8,
md: 16,
lg: 24,
},
};
-
Использование StyleSheet.create() или tailwind-rn
-
Оборачивать приложение в ThemeProvider (через Context или библиотеку вроде styled-components)
-
Хранить глобальные переменные и стили отдельно от компонентов
UI-компоненты
Все переиспользуемые компоненты, не привязанные к бизнес-логике, выносятся в shared/ui/:
<Button onPress={handleSubmit} title="Сохранить" variant="primary" />
<Avatar source={{ uri: user.avatar }} size="lg" />
<Modal visible={isOpen} onClose={closeModal}>...</Modal>
-
Использование prop-driven архитектуры
-
Универсальность: все стили настраиваются через props
Переиспользуемые блоки
-
shared/components/ — часто используемые секции (Header, Loader, ErrorBoundary)
-
shared/utils/ — форматирование дат, строки, работа с массивами
-
shared/hooks/ — кастомные хуки (useDebounce, usePagination, useKeyboard)
Работа с авторизацией
-
Авторизация через authSlice или authContext
-
Сохранение токенов в AsyncStorage/SecureStore
-
Защищённые маршруты: PrivateRoute, AuthGuard
{isAuthenticated ? <MainStack /> : <AuthStack />}
- Обновление токена (refresh) через интерсепторы или middleware
Тестирование
-
Jest для юнит-тестов
-
@testing-library/react-native для компонентов
-
Detox для E2E
Организация по уровням:
/\__tests__
/unit
/integration
/e2e
Поддержка CI (GitHub Actions, Bitrise) для прогонки тестов.
Работа с хранилищем и оффлайн-режимом
-
Кэширование данных через react-query, redux-persist, AsyncStorage
-
Работа в оффлайне: сохранение в SQLite, WatermelonDB, realm
-
Синхронизация при восстановлении соединения
Push-уведомления и Background задачи
-
Firebase Cloud Messaging (FCM)
-
OneSignal
-
Обработка через react-native-push-notification или expo-notifications
-
Background Sync через react-native-background-fetch, expo-task-manager
Монорепозитории и модульность
Для крупных команд может использоваться:
-
Monorepo (Turborepo, Nx)
-
Разделение на пакеты: @app/ui, @app/core, @app/utils
Модули могут быть изолированы и использоваться повторно в других проектах.
Безопасность
-
Использование react-native-keychain или expo-secure-store
-
Защита маршрутов
-
Защита критичных экранов (например, повторная авторизация)
-
Проверка версий, device check, root detection
DevOps и окружения
-
Разделение окружений: .env.development, .env.production
-
Использование react-native-config или expo-constants
-
CI/CD: автоматическая сборка и деплой через GitHub Actions, AppCenter, Bitrise
Логгирование и мониторинг
-
Интеграция Sentry или Bugsnag
-
Пользовательская аналитика: Firebase Analytics, Mixpanel
-
Crashlytics для логирования падений
-
Встроенные логгеры logger.ts с уровнями: info, warn, error
Выстраивание архитектуры — это не только структура файлов, но и культура кодирования, согласованные подходы к бизнес-логике, изоляция зависимостей, тестируемость, переиспользуемость и гибкость масштабирования. Успешный масштаб проекта достигается при чётком разделении ответственности и согласованной командной работе.