Що робить reaction()?
Що таке reaction()
reaction()- це функція MobX, яка реагує (реактивно) на зміну певних спостережуваних (observable) даних і виконує побічний ефект (side effect), коли вони змінюються.
Можна сказати, що це аналог useEffect() з React,
але працює на рівні MobX, і без участі React-компонента.
1. Базовий синтаксис
import { observable, reaction } from "mobx"
const price = observable.box(100)
const quantity = observable.box(2)
// реакція: стежимо за зміною total
reaction(
() => price.get() * quantity.get(), // функція-трекер (що відстежувати)
(total, prevTotal) => { // ефект (що робити при зміні)
console.log(`Total changed: ${prevTotal} → ${total}`)
}
)
price.set(120) // Total changed: 200 → 240
quantity.set(3) // Total changed: 240 → 360MobX:
- Викликає "трекер" (перша функція), щоб дізнатися залежності,
- Стежить за ними,
- Щоразу, коли результат змінюється, викликає побічний ефект (друга функція).
2. У чому відмінність від autorun()
autorun() виконується щоразу, коли залежні observable використовуються в тілі.
reaction() - більш цільова:
вона відстежує лише те, що повертає перша функція (selector).
| autorun() | reaction() | |
|---|---|---|
| Що відстежує | Все, що використовується всередині тіла | Лише результат функції-трекера |
| Коли викликається | Щоразу при зміні залежностей | Лише якщо результат справді змінився |
| Використовується для | Логів, загальних реакцій | Точного контролю side-ефектів |
Тобто reaction() - це "тонке налаштування" реактивних побічних ефектів.
3. Приклад з фільтрацією змін
import { makeAutoObservable, reaction } from "mobx"
class CartStore {
items = []
constructor() {
makeAutoObservable(this)
// стежимо за кількістю товарів
reaction(
() => this.items.length,
(count) => {
console.log(`Кількість товарів змінилася: ${count}`)
}
)
}
add(item) {
this.items.push(item)
}
}
const cart = new CartStore()
cart.add("T-shirt") // → Кількість товарів змінилася: 1
cart.add("Jeans") // → Кількість товарів змінилася: 2Тут реакція спрацьовує лише при зміні довжини масиву,
а не при кожній зміні items.
4. Параметри reaction()
reaction(
expression, // функція, яка повертає "що відстежувати"
effect, // функція, що викликається при зміні
options? // опції
)Опції:
| Опція | Що робить | Приклад |
|---|---|---|
fireImmediately | запустити ефект одразу при ініціалізації | { fireImmediately: true } |
equals | кастомна функція порівняння (типово !==) | { equals: (a, b) => JSON.stringify(a) === JSON.stringify(b) } |
delay | затримка виклику ефекту (дебаунс) | { delay: 300 } |
name | ім'я для дебагу | { name: "cartReaction" } |
Приклад з fireImmediately
reaction(
() => store.user,
(user) => {
console.log("Поточний користувач:", user)
},
{ fireImmediately: true }
)Виведе користувача одразу при ініціалізації,
а потім при кожній зміні store.user.
5. Приклад "побічного ефекту" (API-запит)
reaction(
() => store.searchQuery,
async (query) => {
if (query.length < 3) return
const results = await api.search(query)
store.results = results
},
{ delay: 400 } // debounce
)Це класичний сценарій: реакція на зміну observable (наприклад, рядка пошуку), і виконання асинхронного ефекту (запит до API).
6. Відмінність від computed
| computed | reaction | |
|---|---|---|
| Що робить | Обчислює значення | Запускає побічний ефект |
| Повертає щось | Так | Ні |
| Кешує результат | Так | Ні |
| Змінює стан | Ні | Може |
| Використовується для | Derived data | Side-effects |
computed - "чисте" значення,
reaction - "брудна дія" (ефект).
7. Приклад у класі
class AuthStore {
user = null
constructor() {
makeAutoObservable(this)
reaction(
() => this.user?.isLoggedIn,
(isLoggedIn) => {
if (isLoggedIn) {
console.log("Користувач увійшов у систему")
} else {
console.log("Користувач вийшов")
}
},
{ fireImmediately: true }
)
}
}Це дозволяє реагувати на зміну стану (наприклад, при логіні / логауті), без логіки всередині UI-компонентів.
8. Очищення (dispose)
reaction() повертає функцію, яка зупиняє спостереження:
const dispose = reaction(
() => store.count,
(count) => console.log("count:", count)
)
dispose() // тепер реакція більше не спрацюєЦе корисно при ручному керуванні життєвим циклом (наприклад, поза React).
9. Візуально
[observable] → [reaction → side effect]Приклад:
store.query → reaction → api.search(query)
Підсумок
reaction()- це реактивний спостерігач, який стежить за конкретними даними (observable) і виконує побічний ефект при їх зміні.
Формула запам'ятовування:
reaction(trackFn, effectFn)= "Стеж за результатомtrackFnі викликайeffectFn, якщо він змінився."
Коли використовувати:
Коли потрібно запускати ефект при зміні observable, але не викликати його на кожен ререндер. Наприклад:
- Запити до API при зміні стану;
- Збереження даних у
localStorage; - Логування, трекінг, аналітика;
- Реакція на зміну авторизації, фільтрів, маршрутів.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.