Reactions
Reactions запускают side-эффекты при изменении observables.
Три типа реакций
1. autorun
Запускается сразу и при каждом изменении отслеживаемых observables:
import { observable, autorun } from 'mobx';
const store = observable({ count: 0 });
autorun(() => {
console.log(`Count: ${store.count}`);
});
store.count = 5;
Вывод:
Count: 0
Count: 5
2. reaction
Запускается только при изменениях (не сразу):
import { observable, reaction } from 'mobx';
const store = observable({ count: 0 });
reaction(
() => store.count,
(count) => {
console.log(`Count changed to: ${count}`);
}
);
store.count = 5;
Вывод:
Count changed to: 5
3. when
Запускается один раз когда условие становится true:
import { observable, when } from 'mobx';
const store = observable({ isReady: false });
when(
() => store.isReady,
() => {
console.log('Ready!');
}
);
store.isReady = true;
reaction с селектором
Главная фишка reaction - контроль что отслеживать:
const store = observable({
user: {
name: 'Ivan',
email: 'ivan@example.com',
age: 25
}
});
reaction(
() => store.user.email,
(email) => {
console.log(`Email changed: ${email}`);
sendVerificationEmail(email);
}
);
Эффект сработает только при изменении email, не name или age!
Дополнительные параметры
delay (debounce)
reaction(
() => store.searchQuery,
(query) => {
performSearch(query);
},
{ delay: 300 }
);
fireImmediately
reaction(
() => store.value,
(value) => {
console.log(value);
},
{ fireImmediately: true }
);
Теперь сработает сразу, как autorun!
equals (custom comparator)
import { comparer } from 'mobx';
reaction(
() => store.user,
(user) => {
console.log('User changed');
},
{ equals: comparer.identity }
);
Очистка ресурсов (dispose)
Важно: reaction работает бесконечно пока не вызвать dispose!
class Store {
disposer = null;
constructor() {
makeAutoObservable(this);
this.disposer = reaction(
() => this.data,
(data) => console.log(data)
);
}
destroy() {
if (this.disposer) {
this.disposer();
}
}
}
В React:
useEffect(() => {
const dispose = reaction(
() => store.value,
(value) => console.log(value)
);
return () => dispose();
}, []);
Сравнение
| autorun | reaction | when | |
|---|---|---|---|
| Отслеживает | Все внутри | Только селектор | Только селектор |
| Запуск | Сразу + изменения | Только изменения | Один раз при true |
| Предыдущее значение | ❌ | ✅ | ❌ |
Когда что использовать?
autorun
autorun(() => {
document.title = store.pageTitle;
});
Когда нужно выполнить сразу и при каждом изменении.
reaction
reaction(
() => store.filters,
(filters) => {
updateURL(filters);
}
);
Когда нужна реакция только на изменения.
when
when(
() => store.isLoaded,
() => {
showContent();
}
);
Когда нужно дождаться условия один раз.
🎮 Интерактивный пример
Ваш пример из практики - валидация кода с autorun, reaction и when:
Reactions: autorun + reaction + when
const MOCK_VALIDATE_CODE = "1234";
const store = observable({
email: "",
validateCode: "",
validate: false,
});
console.log('=== Настройка реакций ===\n');
autorun(() => {
if (!store.validate) {
console.log('🔵 autorun: Пройдите email валидацию');
} else {
console.log('🔵 autorun: Валидация пройдена!');
}
});
const validateCode = action((code) => {
store.validate = code === MOCK_VALIDATE_CODE;
});
const changeCode = action(value => {
store.validateCode += value;
console.log('⌨️ Entry:', store.validateCode);
});
reaction(() => store.validateCode, code => {
if (code.length === 4) {
console.log('🟢 reaction: Код введен, проверяем...');
validateCode(code);
}
});
when(() => store.validate, () => {
console.log('🎉 when: Email validation success!');
});
console.log('\n=== Начинаем ввод кода ===\n');
for (let i = 1; i <= 4; i++) {
changeCode(String(i));
}Три типа реакций в действии:
- 🔵 autorun - запускается сразу и при каждом изменении
- 🟢 reaction - только при изменениях (контроль зависимостей)
- 🎉 when - однократное выполнение при условии
🎯 3. Проверьте себя
Тест: Reactions
1 / 5Когда запускается autorun первый раз?
A.При первом изменении observable
B.Сразу при создании
C.Через секунду после создания
D.Никогда сам, нужно вызвать
📊 Прогресс: 0 / 5 вопросов
🎴 4. Anki карточки
Карточки для Anki
8 карточек💡 Как импортировать в Anki:
- Нажмите "Скачать для Anki"
- В Anki: Файл → Импортировать
- Выберите скачанный .csv файл
- Тип: "Базовый (с обратной карточкой)"
- Разделитель полей: Запятая
- Импортировать!
📊 Результат обучения
После изучения этой темы вы:
- ✅ Понимаете три типа реакций
- ✅ Знаете когда использовать autorun, reaction, when
- ✅ Умеете управлять зависимостями
- ✅ Прошли тест на понимание
- ✅ Получили карточки для Anki
Следующий шаг: изучите Actions - изменение состояния! 🚀