Настройка архитектуры MobX для React Native-приложения
Вы создаёте мобильное приложение на React Native и понимаете, что стейт-менеджмент через Redux забирает до 40% времени на написание boilerplate-кода. За 5+ лет работы с React Native и 50+ реализованных проектов мы выяснили: MobX — самый быстрый способ внедрить реактивное управление состоянием. Экшены, редьюсеры, селекторы, нормализация — всё это можно заменить лаконичным наблюдаемым хранилищем. MobX — реактивный State Manager, основанный на observable-значениях. Вместо диспатчинга — прямые мутации, вместо mapStateToProps — observer-обёртка. Для React Native с mobx-react-lite мы получаем компактный код без лишних обёрток. Свяжитесь с нами для оценки вашего проекта.
Наша команда настраивает MobX-архитектуру под ключ, гарантируя совместимость с TypeScript, навигацией и push-уведомлениями. Оценим ваш проект и предложим сроки от 2 дней. Получите консультацию — мы расскажем, как сократить код на 60%.
Проблемы, которые решаем
-
Избыточный boilerplate: Redux требует actionTypes, action creators, reducers, combineReducers — для каждого модуля. MobX с
makeAutoObservableавтоматически помечает поля и методы за вас. -
Асинхронные обновления: После
awaitтеряется контекст действия. ИспользуемrunInActionдля безопасных мутаций — это предотвращает случайные изменения вне действия. -
Сложность интеграции: С React Native часто возникает проблема с
useEffectи множественными подписками. MobX сobserver()автоматически отслеживает только используемые observable, минимизируя перерисовки.
Почему MobX лучше Redux для React Native?
import { makeAutoObservable, runInAction } from 'mobx'; class ProfileStore { profile: UserProfile | null = null; isLoading = false; error: string | null = null; constructor(private userRepository: UserRepository) { makeAutoObservable(this); } async loadProfile(userId: string) { this.isLoading = true; this.error = null; try { const profile = await this.userRepository.getProfile(userId); runInAction(() => { this.profile = profile; this.isLoading = false; }); } catch (e) { runInAction(() => { this.error = (e as Error).message; this.isLoading = false; }); } } get displayName() { return this.profile ? `${this.profile.firstName} ${this.profile.lastName}` : ''; } } makeAutoObservable автоматически помечает поля как observable, методы как action, геттеры как computed. В strict mode MobX требует action, поэтому runInAction обязателен для асинхронных сценариев — это предотвращает случайные мутации вне действия.
В компоненте:
const ProfileScreen = observer(({ userId }: { userId: string }) => { const { profileStore } = useStores(); useEffect(() => { profileStore.loadProfile(userId); }, [userId]); if (profileStore.isLoading) return <ActivityIndicator />; if (profileStore.error) return <ErrorView message={profileStore.error} />; return <ProfileView name={profileStore.displayName} />; }); observer() из mobx-react-lite делает компонент реактивным: перерисовка только при изменении использованных observable-свойств.
Сравнение производительности: MobX vs Redux
| Параметр | MobX | Redux |
|---|---|---|
| Строк кода на store | 30 | 70 |
| Время на реализацию | 2-3 дня | 4-6 дней |
| Количество файлов | 1 | 4+ |
| Перерисовка при изменении | 1 компонент | Зависит от connect |
Как избежать лишних перерисовок с MobX?
React Context при изменении данных вызывает перерендер всех потребителей, а MobX точечно обновляет только зависимые компоненты. В таблице ниже — сравнение метрик для типового профильного экрана:
| Параметр | MobX | React Context |
|---|---|---|
| Код для создания хранилища | 20 строк | 35 строк (Reducer + Provider) |
| Перерисовка на изменение профиля | 1 компонент | Все подписчики Context |
| Время на реализацию | 2–3 дня | 3–5 дней |
Подробнее о контексте
Для DI используем Provider, но передаём не данные, а готовый store — это позволяет избежать лишних rerender-ов.Контекст для DI
Передаём stores через React Context без Provider-ада:
const StoreContext = createContext<RootStore | null>(null); export const useStores = () => useContext(StoreContext)!; // В App.tsx const rootStore = new RootStore(); <StoreContext.Provider value={rootStore}> <AppNavigator /> </StoreContext.Provider> RootStore создаёт все store-ы и передаёт зависимости между ними.
Главный аргумент за MobX
По сравнению с Redux — в два-три раза меньше кода для той же функциональности. Нет actionTypes, нет mapStateToProps, нет нормализации store. Для команд, которые ценят скорость разработки над строгостью — MobX выигрывает. Официальная документация MobX рекомендует использовать makeAutoObservable для упрощения настройки.
Аргумент против: меньше предсказуемости. Мутации происходят напрямую, без явного лога диспатчей. Для отладки подключаем mobx-react-devtools или mobx-logger.
Что входит в работу
- Настройка
RootStoreс инжекцией зависимостей. -
StoreContext+useStoresхук. - Базовый Store-шаблон с
makeAutoObservable. - Интеграция
mobx+mobx-react-liteс бабелом (по необходимости). - Unit-тесты store-логики через Jest (чистые тесты без React).
- Документация по архитектуре и доступам.
- Видео-туториал для команды.
- Поддержка после деплоя (2 недели).
Процесс работы
- Анализ требований и текущей архитектуры (1 день).
- Проектирование структуры Store и связей (0.5 дня).
- Реализация шаблона и базового Store (0.5 дня).
- Интеграция с модулями приложения (аутентификация, профиль, покупки) — 1 день.
- Тестирование и отладка (0.5 дня).
- Передача и обучение команды (0.5 дня).
Сроки ориентировочно
Настройка MobX-архитектуры с нуля — от 2 до 4 дней в зависимости от сложности приложения. Стоимость рассчитывается индивидуально — свяжитесь с нами для оценки проекта.
Типичные ошибки при внедрении
- Забывают обернуть асинхронные мутации в
runInAction— получают warning в strict mode. - Используют один большой Store вместо нескольких маленьких — теряют производительность.
- Не используют
computedдля производных данных — пересчёт на лету замедляет рендер.
Если вы столкнулись с одной из этих проблем — закажите настройку MobX под ключ. Мы настраивали MobX в проектах с 50+ экранами и гарантируем совместимость с TypeScript, навигацией и push-уведомлениями.







