59. MobX: Введение
MobX: Введение в реактивное программирование 🧲
Заголовок раздела «MobX: Введение в реактивное программирование 🧲»MobX — это библиотека для управления состоянием, основанная на принципах реактивного программирования. Вместо того чтобы описывать как обновлять UI, ты просто описываешь что является состоянием — и MobX сам следит за всеми зависимостями и обновляет только то, что нужно. ✨
1. Что такое реактивное программирование? 🤔
Заголовок раздела «1. Что такое реактивное программирование? 🤔»Представь электронную таблицу Excel. Ты вводишь число в ячейку A1, и все формулы, которые зависят от A1, автоматически пересчитываются. Тебе не нужно вручную говорить Excel “пересчитай B1 и C3” — он делает это сам.
MobX работает точно так же! Ты объявляешь данные как наблюдаемые (observable), а потом любой код, который их читает, автоматически становится реактивным — он будет выполняться заново при изменении данных.
import { makeAutoObservable } from 'mobx';
class CounterStore { count = 0; // 👈 это наблюдаемое значение
constructor() { makeAutoObservable(this); }
increment() { this.count++; // 👈 это действие, меняющее состояние }}
// Любой компонент, который читает store.count,// автоматически перерендерится при его изменении!2. Три кита MobX 🐋
Заголовок раздела «2. Три кита MobX 🐋»MobX строится на трёх фундаментальных концепциях:
🟣 Observable (Наблюдаемые данные)
Заголовок раздела «🟣 Observable (Наблюдаемые данные)»Это твоё состояние — объекты, массивы, примитивы, которые MobX отслеживает.
import { observable, makeObservable } from 'mobx';
class Store { @observable count = 0; @observable name = 'Яша'; @observable items: string[] = [];}🔵 Actions (Действия)
Заголовок раздела «🔵 Actions (Действия)»Единственный правильный способ изменять observable-данные. Это как “команды” в военном лагере — только через официальный приказ.
import { action, makeObservable } from 'mobx';
class Store { @action increment() { this.count++; }
@action setName(name: string) { this.name = name; }}🟢 Reactions (Реакции)
Заголовок раздела «🟢 Reactions (Реакции)»Код, который автоматически запускается при изменении observable-данных. Реакции — это “слушатели” изменений.
import { autorun, reaction } from 'mobx';
// autorun — запускается сразу и при каждом измененииautorun(() => { console.log('Count изменился:', store.count);});
// reaction — запускается только когда возвращаемое значение изменяетсяreaction( () => store.count, (count) => console.log('Новое значение:', count));3. Магия отслеживания зависимостей ✨
Заголовок раздела «3. Магия отслеживания зависимостей ✨»Самое крутое в MobX — это автоматическое отслеживание зависимостей. Тебе не нужно писать connect(), mapStateToProps() или список зависимостей как в useEffect. MobX сам видит, какие observable читаются во время выполнения реакции.
const store = observable({ firstName: 'Иван', lastName: 'Петров', age: 25,});
// MobX автоматически понимает, что эта реакция// зависит от firstName И lastName, но НЕ от ageautorun(() => { console.log(`${store.firstName} ${store.lastName}`); // age здесь не читается — изменение age не вызовет эту реакцию!});4. MobX vs Redux vs Zustand 🥊
Заголовок раздела «4. MobX vs Redux vs Zustand 🥊»Выбор стейт-менеджера — это как выбор инструмента. Молоток — не лучше отвёртки, просто для разных задач.
| Характеристика | MobX | Redux Toolkit | Zustand |
|---|---|---|---|
| Философия | Мутабельность (ООП) | Иммутабельность (FP) | Мутабельность (лёгкость) |
| Бойлерплейт | 🟢 Минимум | 🟡 Средний | 🟢 Минимум |
| Размер бандла | ~60 кб | ~40 кб | ~3 кб |
| TypeScript | 🟢 Отличный | 🟡 Хороший | 🟢 Отличный |
| DevTools | 🟡 Есть | 🟢 Отличные | 🟡 Базовые |
| Кривая обучения | 🟡 Средняя | 🔴 Высокая | 🟢 Низкая |
| OOP-стиль | 🟢 Идеальный | 🔴 Нет | 🟡 Частично |
| Реактивность | 🟢 Автоматическая | 🔴 Ручная | 🟡 Полуавтоматическая |
| Подходит для | Сложный стейт, ООП | Предсказуемость, дебаггинг | Простые приложения |
5. Мутабельность vs Иммутабельность 🔄
Заголовок раздела «5. Мутабельность vs Иммутабельность 🔄»Redux требует, чтобы ты никогда не мутировал состояние. Каждое изменение создаёт новый объект:
// Redux — иммутабельный подходconst newState = { ...state, count: state.count + 1, // создаём новый объект!};MobX позволяет напрямую изменять состояние, как в обычном JavaScript:
// MobX — мутабельный подходstore.count++; // просто изменяем! MobX отследит это самstore.items.push('новый элемент');store.user.name = 'Петя';Это делает MobX очень интуитивным, особенно если ты знаком с ООП.
6. Когда выбирать MobX? 🎯
Заголовок раздела «6. Когда выбирать MobX? 🎯»✅ MobX — хороший выбор когда:
- Ты пишешь приложение в ООП-стиле с классами
- У тебя сложная доменная модель с множеством взаимосвязей
- Команда привыкла к Angular/Vue (похожая реактивность)
- Хочешь минимум бойлерплейта
- Данные часто меняются (игры, real-time приложения)
❌ Лучше выбрать другой инструмент когда:
- Нужны отличные DevTools для time-travel debugging → Redux
- Маленькое приложение с простым стейтом → Zustand или useState
- Команда работает в функциональном стиле → Redux Toolkit
- Нужна максимальная предсказуемость → Redux
7. Быстрый старт 🚀
Заголовок раздела «7. Быстрый старт 🚀»npm install mobx mobx-react-liteimport { makeAutoObservable } from 'mobx';
class AppStore { count = 0;
constructor() { makeAutoObservable(this); }
increment() { this.count++; }}
export const store = new AppStore();import { observer } from 'mobx-react-lite';import { store } from './store';
// observer() — оборачивает компонент, делая его реактивнымconst App = observer(() => ( <button onClick={() => store.increment()}> Клики: {store.count} </button>));Резюме 📝
Заголовок раздела «Резюме 📝»MobX — это мощный инструмент реактивного программирования, который делает управление состоянием простым и интуитивным. Главные идеи:
- 🟣 Observable — наблюдаемые данные (твой стейт)
- 🔵 Action — единственный способ менять стейт
- 🟢 Reaction/Computed — автоматические ответы на изменения
- ✨ Автоматическое отслеживание зависимостей — MobX сам знает, кто от чего зависит
- 🔄 Мутабельность — меняй состояние как обычный JS объект
В следующих уроках мы разберём каждую концепцию подробно! 💪