Перейти к основному содержимому

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();
}, []);

Сравнение

autorunreactionwhen
ОтслеживаетВсе внутриТолько селекторТолько селектор
ЗапускСразу + измененияТолько измененияОдин раз при 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 карточек
📝 Что такое reaction в MobX?
📝 Три типа reactions в MobX?
📝 autorun vs reaction - когда что использовать?
📝 Что отслеживается в reaction?
📝 Когда when автоматически удаляется?
📝 Что делает опция delay в reaction?
📝 Что делает fireImmediately в reaction?
📝 Нужно ли делать dispose для reactions?
💡 Как импортировать в Anki:
  1. Нажмите "Скачать для Anki"
  2. В Anki: Файл → Импортировать
  3. Выберите скачанный .csv файл
  4. Тип: "Базовый (с обратной карточкой)"
  5. Разделитель полей: Запятая
  6. Импортировать!

📊 Результат обучения

После изучения этой темы вы:

  • ✅ Понимаете три типа реакций
  • ✅ Знаете когда использовать autorun, reaction, when
  • ✅ Умеете управлять зависимостями
  • ✅ Прошли тест на понимание
  • ✅ Получили карточки для Anki

Следующий шаг: изучите Actions - изменение состояния! 🚀