Що таке computed value в MobX?
Що таке computed value
Computed value (або "обчислювана властивість") - це значення, яке автоматично перераховується, коли змінюються спостережувані (observable) дані, від яких воно залежить.
Іншими словами:
computed - це "реактивний
get", який MobX кешує і перераховує лише за потреби.
1. Приклад наочно
import { makeAutoObservable } from "mobx"
class TodoStore {
todos = [
{ title: "Купити хліб", done: true },
{ title: "Подзвонити другу", done: false },
]
constructor() {
makeAutoObservable(this)
}
// computed
get completedCount() {
return this.todos.filter(t => t.done).length
}
}
const store = new TodoStore()
console.log(store.completedCount) // 1
store.todos[1].done = true
console.log(store.completedCount) // 2MobX сам стежить, які observable використовуються в completedCount,
і перерахує його лише коли зміняться потрібні поля (todos[i].done).
2. У чому відмінність від звичайного геттера
Якби це був звичайний JS-геттер, він би перераховувався при кожному виклику, навіть якщо нічого не змінилося.
Computed у MobX працює інакше:
- він запам'ятовує (кешує) останнє значення;
- перераховується лише якщо залежності змінилися.
Це робить computed дуже ефективним.
3. Як MobX відстежує залежності
MobX будує граф залежностей між observable і computed. Коли observable-дані змінюються, MobX інвалідує лише потрібні computed-властивості.
Приблизно так:
todos.done → completedCount → UIЯкщо todos змінилися → перерахувати completedCount → оновити UI.
Якщо змінилося щось інше (не пов'язане з todos) - completedCount не чіпається.
4. Як оголосити computed
Є 2 способи:
Через геттер:
get fullName() {
return `${this.firstName} ${this.lastName}`
}(Якщо використовується makeAutoObservable, MobX сам визначить, що це computed.)
Через makeObservable:
import { makeObservable, observable, computed } from "mobx"
class UserStore {
firstName = "Alex"
lastName = "Smith"
constructor() {
makeObservable(this, {
firstName: observable,
lastName: observable,
fullName: computed,
})
}
get fullName() {
return `${this.firstName} ${this.lastName}`
}
}5. Переваги computed
| Перевага | Опис |
|---|---|
| Автоматичне оновлення | Перераховується при зміні залежностей |
| Кешування | Не перераховується без потреби |
| Іммутабельність | Не можна напряму змінити (read-only) |
| Проста декларативність | Показує "що залежить від чого" |
| Оптимізація UI | Компоненти re-render'яться лише при зміні залежних даних |
6. Відмінність computed від action і observable
| Тип | Що робить | Змінює дані? | Реактивно оновлюється? |
|---|---|---|---|
| observable | зберігає стан | Так | Так |
| action | змінює observable | Так | Ні |
| computed | обчислює похідні значення | Ні | Так |
7. Приклад з реактивним UI
import { observer } from "mobx-react-lite"
const TodoInfo = observer(({ store }) => (
<div>
<p>Усього завдань: {store.todos.length}</p>
<p>Виконано: {store.completedCount}</p>
</div>
))Компонент автоматично оновиться,
коли зміниться todos або перерахується completedCount.
8. Кешування в дії
console.log(store.completedCount) // 2 - обчислить
console.log(store.completedCount) // 2 - візьме з кешу
store.todos.push({ title: "Нова", done: false })
console.log(store.completedCount) // 2 - перерахує зновуMobX кешує результат, поки observable-залежності не змінилися.
9. "computed value" поза класами (реактивна функція)
Можна створювати computed-значення вручну:
import { observable, computed } from "mobx"
const price = observable.box(100)
const quantity = observable.box(2)
const total = computed(() => price.get() * quantity.get())
console.log(total.get()) // 200
price.set(120)
console.log(total.get()) // 240Тут computed() працює як реактивна функція,
MobX сам відстежує залежності між price, quantity і total.
ПІДСУМОК
Computed value - це похідне (derived) значення, яке MobX автоматично перераховує при зміні залежностей, і кешує, щоб не робити зайву роботу.
Формула запам'ятовування
Observable → зберігає дані Action → змінює дані Computed → обчислює з даних Observer (React) → відображає дані
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.