Що таке action у MobX?
Просте визначення
actionу MobX - це функція, яка змінює спостережувані (observable) дані.MobX відстежує всі зміни, що відбуваються всередині action, і оновлює залежності (компоненти, обчислення) одним пакетом - без зайвих реакцій між проміжними кроками.
Чому action існує
MobX розділяє два типи коду:
| Тип | Призначення |
|---|---|
| Reactive (реактивний) | обчислює або відображає дані (наприклад, компонент React чи computed) |
| Active (активний) | змінює дані (наприклад, подія кліку, API-запит тощо) |
Action - це межа, де відбуваються зміни в observable-стані. Вони забезпечують:
- передбачуваність (усі зміни контролюються);
- оптимізацію (оновлення групуються);
- чисту реактивність (немає реакцій "посередині" обчислень).
Приклад 1 - без action
import { makeObservable, observable } from 'mobx'
class Counter {
count = 0
constructor() {
makeObservable(this, {
count: observable,
})
}
increment() {
this.count++ // MobX все одно працює, але не оптимально
}
}Тут increment() змінює стан, але MobX не знає, що це контрольована дія.
Приклад 2 - з action
import { makeObservable, observable, action } from 'mobx'
class Counter {
count = 0
constructor() {
makeObservable(this, {
count: observable,
increment: action, // оголошуємо як action
})
}
increment() {
this.count++
}
}Тепер MobX знає, що increment() - це action, і:
- не запускає реакції (оновлення UI) після кожної мутації;
- відкладає реакцію до кінця action;
- групує всі зміни в один батч → менше перерендерів і обчислень.
Автоматичне визначення action
Якщо ти використовуєш сучасний MobX (через makeAutoObservable),
він сам позначає методи як action, а геттери - як computed:
import { makeAutoObservable } from 'mobx'
class TodoStore {
todos = []
constructor() {
makeAutoObservable(this) // все автоматично
}
addTodo(text) {
this.todos.push({ text, done: false }) // action
}
get completed() {
return this.todos.filter(t => t.done) // computed
}
}Чому це важливо
Припустимо, ти оновлюєш кілька властивостей поспіль:
userStore.updateProfile = action(() => {
userStore.name = 'Alex'
userStore.age = 25
userStore.email = 'alex@example.com'
})Без action MobX викликав би реакцію після кожного присвоєння → до трьох перерендерів поспіль.
З action MobX робить це одним пакетом, викликаючи реакцію лише один раз - після завершення блоку.
Типи action
| Тип | Опис |
|---|---|
action(fn) | вручну огортає функцію в action |
@action (декоратор) | старий синтаксис для класів |
makeObservable(..., { method: action }) | явне оголошення |
makeAutoObservable() | автоматичне визначення методів як action |
Приклад 3 - явне оголошення поза класом
import { observable, action } from 'mobx'
const state = observable({
count: 0,
inc: action(function () {
this.count++
}),
})Під капотом
Action:
- Позначає початок "пакета змін" (
startBatch); - Вимикає тимчасові реакції;
- Виконує зміни в
observable; - Після завершення - одним разом сповіщає всі залежні реакції (
endBatch).
Саме це робить MobX надефективним: UI не перерендерюється при кожній дрібниці - лише коли вся дія завершена.
Підсумок
| Що робить | Приклад |
|---|---|
| Огортає зміну стану | increment = action(() => this.count++) |
| Групує оновлення | Один батч замість кількох реакцій |
| Підвищує продуктивність | Менше перерендерів |
| Робить код передбачуваним | Усі зміни проходять через actions |
Автоматично створюється при makeAutoObservable | Так |
Коротко
action- це "офіційне місце", де ти змінюєшobservable-дані. Воно робить зміни контрольованими, батчованими і передбачуваними, забезпечуючи чисту реактивність і високу продуктивність.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.