Современный фронтенд уже давно перестал быть набором статических страниц. Даже небольшие приложения сегодня умеют работать с авторизацией, корзиной товаров, уведомлениями, фильтрами, сложными формами, асинхронными запросами и десятками экранов. Все эти данные постоянно меняются, и чем больше становится приложение, тем чаще разработчики начинают задумываться об управлении состоянием.
Именно здесь появляются библиотеки state management. Кто-то начинает знакомство с Context API, кто-то сразу берет Redux, кто-то работает с Zustand, Recoil или Jotai. Но существует инструмент, который уже много лет остается одним из самых удобных решений благодаря своей простоте и практически “живому” поведению — MobX.
Интересно, что многие разработчики относятся к MobX с осторожностью. Одни ценят MobX за высокий уровень автоматизации, другие, наоборот, считают такой подход недостаточно явным и предпочитают библиотеки с более предсказуемым потоком данных. На практике же MobX используется в достаточно крупных коммерческих продуктах, а его подход к реактивности до сих пор считается одним из самых элегантных среди существующих библиотек управления состоянием.
Главная идея MobX заключается в том, что разработчику практически не приходится самостоятельно описывать процесс обновления интерфейса. Вместо этого библиотека отслеживает изменения данных и автоматически обновляет только те части приложения, которые действительно используют изменившееся состояние.
Именно здесь появляются библиотеки state management. Кто-то начинает знакомство с Context API, кто-то сразу берет Redux, кто-то работает с Zustand, Recoil или Jotai. Но существует инструмент, который уже много лет остается одним из самых удобных решений благодаря своей простоте и практически “живому” поведению — MobX.
Интересно, что многие разработчики относятся к MobX с осторожностью. Одни ценят MobX за высокий уровень автоматизации, другие, наоборот, считают такой подход недостаточно явным и предпочитают библиотеки с более предсказуемым потоком данных. На практике же MobX используется в достаточно крупных коммерческих продуктах, а его подход к реактивности до сих пор считается одним из самых элегантных среди существующих библиотек управления состоянием.
Главная идея MobX заключается в том, что разработчику практически не приходится самостоятельно описывать процесс обновления интерфейса. Вместо этого библиотека отслеживает изменения данных и автоматически обновляет только те части приложения, которые действительно используют изменившееся состояние.
Что такое состояние приложения
Практически любое React-приложение можно представить как совокупность данных.
Это может быть пользователь после авторизации, список товаров интернет-магазина, результаты поиска, текущая тема оформления, язык интерфейса, открытые модальные окна или результаты запросов к серверу.
Пока приложение состоит из нескольких компонентов, достаточно обычного useState. Но спустя некоторое время появляются ситуации, когда одно и то же состояние необходимо использовать сразу в нескольких местах.
Например:
Если каждый компонент начинает самостоятельно хранить одинаковые данные, довольно быстро возникает рассинхронизация. Именно поэтому состояние постепенно выносится в единое хранилище.
Это может быть пользователь после авторизации, список товаров интернет-магазина, результаты поиска, текущая тема оформления, язык интерфейса, открытые модальные окна или результаты запросов к серверу.
Пока приложение состоит из нескольких компонентов, достаточно обычного useState. Но спустя некоторое время появляются ситуации, когда одно и то же состояние необходимо использовать сразу в нескольких местах.
Например:
- Корзина отображается в Header;
- Количество товаров используется на странице оформления заказа;
- Информация о пользователе нужна практически на каждом экране;
- Фильтры одновременно влияют на несколько компонентов.
Если каждый компонент начинает самостоятельно хранить одинаковые данные, довольно быстро возникает рассинхронизация. Именно поэтому состояние постепенно выносится в единое хранилище.
Чем MobX отличается от других библиотек
Если посмотреть на Redux, то первое, что бросается в глаза — большое количество шаблонного кода. Даже несмотря на Redux Toolkit, разработчику приходится мыслить действиями (actions), редьюсерами, диспатчами и неизменяемым состоянием.
MobX предлагает совершенно другую модель:
Здесь разработчик работает не с событиями, а с обычными объектами JavaScript.
Если значение изменилось, то интерфейс автоматически обновится.
Без ручных подписок. Без dispatch. Без reducer. Без необходимости создавать копии объектов на каждом изменении.
Именно это и называют реактивным программированием.
MobX предлагает совершенно другую модель:
Здесь разработчик работает не с событиями, а с обычными объектами JavaScript.
Если значение изменилось, то интерфейс автоматически обновится.
Без ручных подписок. Без dispatch. Без reducer. Без необходимости создавать копии объектов на каждом изменении.
Именно это и называют реактивным программированием.
Observable — сердце MobX
В основе библиотеки лежит понятие observable.
Observable — это обычный объект, за изменениями которого MobX умеет наблюдать.
Представим простейший Store пользователя:
Observable — это обычный объект, за изменениями которого MobX умеет наблюдать.
Представим простейший Store пользователя:
После вызова makeAutoObservable() все свойства автоматически становятся наблюдаемыми, а методы — действиями, изменяющими состояние.
Разработчику практически ничего дополнительно делать не нужно.
Разработчику практически ничего дополнительно делать не нужно.
Observer — связующее звено между состоянием и интерфейсом
После того как данные стали observable, React должен понимать, когда необходимо выполнить повторный рендер.
Для этого используется компонент observer:
Для этого используется компонент observer:
Теперь компонент будет обновляться только тогда, когда изменится именно name.
Если поменяется другое свойство Store, которое компонент не использует, повторного рендера не произойдет.
Если поменяется другое свойство Store, которое компонент не использует, повторного рендера не произойдет.
Именно такая “точечная” реактивность считается одним из главных преимуществ MobX.
Почему разработчики любят MobX
На первый взгляд кажется, что главное достоинство библиотеки — небольшой объем кода.
Но это далеко не единственное преимущество.
MobX хорошо масштабируется благодаря тому, что состояние можно разбивать на отдельные Store. Каждый отвечает только за свою бизнес-логику, а не превращается в огромный файл на несколько тысяч строк.
Еще одна особенность MobX — возможность изменять состояние напрямую. Если в экосистеме React широко распространен подход с неизменяемыми (immutable) данными, то MobX строится на другой модели: библиотека самостоятельно отслеживает изменения объектов и уведомляет компоненты о необходимости обновления. Для многих разработчиков такой стиль работы оказывается более естественным и позволяет писать меньше шаблонного кода, однако тем, кто привык к философии иммутабельности, может потребоваться некоторое время, чтобы перестроить мышление.
Кроме того, код выглядит максимально естественно. Многие методы Store практически не отличаются от обычных методов классов, поэтому начинающим разработчикам гораздо проще понять происходящее.
Но это далеко не единственное преимущество.
MobX хорошо масштабируется благодаря тому, что состояние можно разбивать на отдельные Store. Каждый отвечает только за свою бизнес-логику, а не превращается в огромный файл на несколько тысяч строк.
Еще одна особенность MobX — возможность изменять состояние напрямую. Если в экосистеме React широко распространен подход с неизменяемыми (immutable) данными, то MobX строится на другой модели: библиотека самостоятельно отслеживает изменения объектов и уведомляет компоненты о необходимости обновления. Для многих разработчиков такой стиль работы оказывается более естественным и позволяет писать меньше шаблонного кода, однако тем, кто привык к философии иммутабельности, может потребоваться некоторое время, чтобы перестроить мышление.
Кроме того, код выглядит максимально естественно. Многие методы Store практически не отличаются от обычных методов классов, поэтому начинающим разработчикам гораздо проще понять происходящее.
Практический пример
Представим интернет-магазин.
Пользователь нажимает кнопку “Добавить в корзину”.
Без централизованного состояния количество товаров приходится передавать через несколько компонентов.
Header → Catalog → Product → Button.
Каждый уровень получает пропсы исключительно для того, чтобы передать их дальше.
Это явление известно как Prop Drilling.
С MobX ситуация выглядит иначе.
Компонент товара просто вызывает метод:
Пользователь нажимает кнопку “Добавить в корзину”.
Без централизованного состояния количество товаров приходится передавать через несколько компонентов.
Header → Catalog → Product → Button.
Каждый уровень получает пропсы исключительно для того, чтобы передать их дальше.
Это явление известно как Prop Drilling.
С MobX ситуация выглядит иначе.
Компонент товара просто вызывает метод:
А Header автоматически показывает новое количество товаров.
Никаких промежуточных пропсов. Никакой ручной синхронизации. Любой компонент приложения получает доступ к одному и тому же состоянию.
Именно поэтому MobX особенно нравится разработчикам крупных интерфейсов.
Никаких промежуточных пропсов. Никакой ручной синхронизации. Любой компонент приложения получает доступ к одному и тому же состоянию.
Именно поэтому MobX особенно нравится разработчикам крупных интерфейсов.
Вычисляемые значения
Еще одна сильная сторона библиотеки — computed-свойства.
Предположим, корзина содержит список товаров.
Итоговую стоимость можно каждый раз вычислять вручную.
Но гораздо удобнее сделать это один раз.
Предположим, корзина содержит список товаров.
Итоговую стоимость можно каждый раз вычислять вручную.
Но гораздо удобнее сделать это один раз.
Теперь при любом изменении списка товаров итоговая стоимость автоматически пересчитывается.
Причем только тогда, когда это действительно необходимо.
MobX самостоятельно кэширует вычисления.
Причем только тогда, когда это действительно необходимо.
MobX самостоятельно кэширует вычисления.
Работа с асинхронными запросами
Практически любое современное приложение взаимодействует с сервером.
Получение пользователей. Авторизация. Обновление профиля. Поиск.
Работа с API в MobX выглядит максимально естественно.
Получение пользователей. Авторизация. Обновление профиля. Поиск.
Работа с API в MobX выглядит максимально естественно.
После изменения свойств loading, users или error интерфейс обновится автоматически. Например, можно показать индикатор загрузки во время выполнения запроса, вывести список пользователей после успешного ответа или отобразить сообщение об ошибке, если запрос завершился неудачно. Разработчику не нужно вручную синхронизировать состояние компонентов. MobX самостоятельно отследит изменения и инициирует обновление только там, где это действительно необходимо.
Когда MobX действительно раскрывается
Наиболее комфортно библиотека ощущается в проектах, где большое количество взаимосвязанных данных.
Это могут быть CRM-системы, административные панели, интернет-магазины, корпоративные приложения, финансовые сервисы или сложные дашборды.
В подобных проектах состояние постоянно изменяется, а один и тот же набор данных используется десятками компонентов.
MobX позволяет избежать большого количества промежуточного кода и сосредоточиться на бизнес-логике.
При этом библиотека одинаково хорошо подходит как для небольших проектов, так и для крупных приложений, если архитектура Store изначально продумана.
Это могут быть CRM-системы, административные панели, интернет-магазины, корпоративные приложения, финансовые сервисы или сложные дашборды.
В подобных проектах состояние постоянно изменяется, а один и тот же набор данных используется десятками компонентов.
MobX позволяет избежать большого количества промежуточного кода и сосредоточиться на бизнес-логике.
При этом библиотека одинаково хорошо подходит как для небольших проектов, так и для крупных приложений, если архитектура Store изначально продумана.
Есть ли у MobX недостатки
Несмотря на большое количество достоинств, идеальных библиотек не существует. Иногда разработчику сложно сразу понять, почему компонент обновился именно сейчас или почему этого не произошло. В Redux поток данных более явный и его проще отслеживать при помощи инструментов разработчика.
Еще один момент связан с архитектурой. Из-за свободы действий разные разработчики могут организовать Store совершенно по-разному. Если команда не придерживается единых соглашений, структура проекта со временем становится менее предсказуемой.
Отдельного внимания заслуживает работа с SSR (Server-Side Rendering). Поскольку MobX использует реактивные объекты и хранит состояние в памяти приложения, при серверном рендеринге необходимо корректно создавать отдельные экземпляры Store для каждого запроса. В противном случае существует риск утечки состояния между пользователями. Современные фреймворки, такие как Next.js, позволяют корректно организовать такую архитектуру, однако по сравнению с клиентскими приложениями настройка SSR требует большей внимательности.
Кроме того, MobX требует понимания принципов реактивности. Если бездумно изменять состояние в неожиданных местах приложения, можно столкнуться со сложными для поиска ошибками. Поэтому даже несмотря на простоту API, библиотека поощряет дисциплину при проектировании архитектуры.
Еще один момент связан с архитектурой. Из-за свободы действий разные разработчики могут организовать Store совершенно по-разному. Если команда не придерживается единых соглашений, структура проекта со временем становится менее предсказуемой.
Отдельного внимания заслуживает работа с SSR (Server-Side Rendering). Поскольку MobX использует реактивные объекты и хранит состояние в памяти приложения, при серверном рендеринге необходимо корректно создавать отдельные экземпляры Store для каждого запроса. В противном случае существует риск утечки состояния между пользователями. Современные фреймворки, такие как Next.js, позволяют корректно организовать такую архитектуру, однако по сравнению с клиентскими приложениями настройка SSR требует большей внимательности.
Кроме того, MobX требует понимания принципов реактивности. Если бездумно изменять состояние в неожиданных местах приложения, можно столкнуться со сложными для поиска ошибками. Поэтому даже несмотря на простоту API, библиотека поощряет дисциплину при проектировании архитектуры.
MobX или Redux?
Этот вопрос остается актуальным уже много лет.
Интересно, что многие команды, которые начинали с Redux, позже переходили на MobX именно из-за более высокой скорости разработки. В то же время существуют проекты, которые наоборот мигрировали с MobX на Redux, когда им понадобился более строгий контроль над архитектурой. Это лишний раз показывает, что выбор инструмента всегда зависит от задач команды, а не от моды.
- Если проект предполагает большое количество разработчиков, строгие процессы, необходимость полностью отслеживать каждое изменение состояния и единый поток данных, Redux по-прежнему остается очень сильным выбором.
- Если же хочется писать меньше шаблонного кода, быстрее разрабатывать функциональность и работать с состоянием максимально естественно, MobX часто оказывается более комфортным решением.
Интересно, что многие команды, которые начинали с Redux, позже переходили на MobX именно из-за более высокой скорости разработки. В то же время существуют проекты, которые наоборот мигрировали с MobX на Redux, когда им понадобился более строгий контроль над архитектурой. Это лишний раз показывает, что выбор инструмента всегда зависит от задач команды, а не от моды.
Что изменилось в современном MobX
За последние годы библиотека стала значительно проще. Если раньше разработчикам приходилось вручную объявлять observable-поля, actions и computed-свойства, то сейчас в большинстве случаев достаточно одного вызова makeAutoObservable().
Это заметно снизило порог входа и сделало код значительно компактнее. При этом производительность библиотеки остается одной из ее сильных сторон: MobX отслеживает зависимости на уровне конкретных используемых данных, благодаря чему часто позволяет избежать лишних перерисовок компонентов без дополнительной оптимизации.
Еще одним плюсом является то, что MobX практически не навязывает архитектуру. Его можно постепенно внедрить даже в существующий проект, не переписывая приложение целиком.
Это заметно снизило порог входа и сделало код значительно компактнее. При этом производительность библиотеки остается одной из ее сильных сторон: MobX отслеживает зависимости на уровне конкретных используемых данных, благодаря чему часто позволяет избежать лишних перерисовок компонентов без дополнительной оптимизации.
Еще одним плюсом является то, что MobX практически не навязывает архитектуру. Его можно постепенно внедрить даже в существующий проект, не переписывая приложение целиком.
MobX уже давно доказал, что управление состоянием может быть одновременно мощным и удобным. Вместо большого количества шаблонного кода разработчик получает реактивную модель, в которой интерфейс автоматически следует за изменениями данных. Благодаря observable-объектам, computed-свойствам и автоматическим обновлениям компонентов код остается компактным, читаемым и близким к обычному JavaScript.
Конечно, MobX не является универсальным ответом на любые архитектурные вопросы. Для некоторых проектов лучше подойдет Redux, где важна строгая предсказуемость, а где-то будет достаточно возможностей Context API или более легковесных библиотек вроде Zustand. Но если нужен инструмент, который позволяет быстро строить сложные интерфейсы без постоянной борьбы с шаблонным кодом, MobX определенно заслуживает внимания.
Пожалуй, именно это и объясняет, почему спустя годы после своего появления библиотека продолжает использоваться в коммерческих проектах и остается одной из самых популярных альтернатив классическим решениям для управления состоянием во фронтенде.
Хотите узнать больше? Изучите другие статьи из раздела:
Конечно, MobX не является универсальным ответом на любые архитектурные вопросы. Для некоторых проектов лучше подойдет Redux, где важна строгая предсказуемость, а где-то будет достаточно возможностей Context API или более легковесных библиотек вроде Zustand. Но если нужен инструмент, который позволяет быстро строить сложные интерфейсы без постоянной борьбы с шаблонным кодом, MobX определенно заслуживает внимания.
Пожалуй, именно это и объясняет, почему спустя годы после своего появления библиотека продолжает использоваться в коммерческих проектах и остается одной из самых популярных альтернатив классическим решениям для управления состоянием во фронтенде.
Хотите узнать больше? Изучите другие статьи из раздела: