MobX и реактивное программирование

MobX — это библиотека для управления состоянием, которая реализует принцип реактивного программирования в JavaScript. Основная идея заключается в автоматическом отслеживании изменений данных и обновлении пользовательского интерфейса без явного вызова методов ререндеринга. В сочетании с Preact, MobX позволяет создавать высокопроизводительные и масштабируемые приложения с минимальным количеством шаблонного кода.

Реактивность достигается через обсерваблы (observables), действия (actions) и вычисляемые значения (computed values).


Обсерваблы (Observables)

Обсервабл — это объект, массив или примитивное значение, за изменениями которого следит MobX. Любое изменение обсервабла автоматически уведомляет подписчиков, вызывая реакцию.

import { observable } from "mobx";

const state = observable({
    count: 0,
    todos: []
});
  • Примитивные обсерваблы позволяют следить за числами, строками и булевыми значениями.
  • Объекты и массивы можно сделать реактивными целиком. Любое изменение внутреннего состояния будет отслежено.

Действия (Actions)

Actions используются для изменения состояния. Они помогают структурировать логику изменения данных и избегать непредсказуемых изменений.

import { action } from "mobx";

const increment = action(() => {
    state.count += 1;
});

Преимущества использования actions:

  • Централизованное управление состоянием.
  • Легкость отслеживания изменений для отладки.
  • Оптимизация ререндеров, так как MobX знает, что обновления происходят внутри action.

Вычисляемые значения (Computed)

Computed значения позволяют определять производные данные, которые автоматически обновляются при изменении зависимостей.

import { computed } from "mobx";

const doubleCount = computed(() => state.count * 2);
  • Computed значения кэшируются, что снижает нагрузку на систему.
  • Они реагируют только на изменения данных, от которых зависят.

Реакции и отслеживание изменений

MobX предоставляет функции autorun и reaction для отслеживания изменений состояния и выполнения побочных эффектов.

import { autorun, reaction } from "mobx";

// Автоматическая реакция на любое изменение состояния
autorun(() => {
    console.log(`Count: ${state.count}`);
});

// Реакция только на конкретное изменение
reaction(
    () => state.count,
    (count, previousCount) => {
        console.log(`Count изменился с ${previousCount} на ${count}`);
    }
);
  • autorun реагирует на все используемые внутри наблюдаемые значения.
  • reaction позволяет контролировать зависимость более тонко, реагируя только на выбранные поля.

Интеграция MobX с Preact

Preact поддерживает работу с MobX через компонентные обёртки и хуки. Для этого используется функция observer из mobx-preact.

import { h } from "preact";
import { observer } from "mobx-preact";

const Counter = observer(() => (
    <div>
        <p>Count: {state.count}</p>
        <button onCl ick={() => increment()}>Increment</button>
        <p>Double: {doubleCount.get()}</p>
    </div>
));

Особенности интеграции:

  • Компоненты, обернутые в observer, автоматически перерендериваются при изменении используемых обсерваблов.
  • MobX минимизирует количество ререндеров, обновляя только те компоненты, которые зависят от изменённого состояния.
  • Можно комбинировать локальные состояния Preact и глобальные состояния MobX для оптимальной производительности.

Структурирование состояния

Для крупных приложений рекомендуется разделять состояние на store-объекты, каждый из которых отвечает за отдельную часть приложения.

class TodoStore {
    todos = observable([]);

    addTodo = action((todo) => {
        this.todos.push(todo);
    });

    get pendingTodos() {
        return this.todos.filter(todo => !todo.completed);
    }
}

const todoStore = new TodoStore();
  • Каждый store инкапсулирует свои данные и методы изменения.
  • Реактивные зависимости между store можно выстраивать через computed и reaction.
  • Это обеспечивает чистую архитектуру и упрощает тестирование.

Производительность и оптимизация

MobX обеспечивает высокую производительность благодаря:

  • Ленивой оценке computed значений.
  • Автоматическому объединению изменений в рамках одного действия.
  • Минимальному количеству перерисовок компонентов.

Советы по оптимизации:

  • Избегать лишних глобальных обсерваблов.
  • Использовать observer только для компонентов, которые зависят от состояния.
  • Разделять большие объекты состояния на более мелкие, реактивные части.

Особенности работы с массивами и объектами

MobX расширяет стандартные методы массивов и объектов, делая их реактивными:

state.todos.push({ id: 1, title: "Learn MobX", completed: false });
state.todos[0].completed = true;
  • Любые мутации массивов (push, splice, sort) автоматически отслеживаются.
  • Изменения вложенных объектов также реактивны, если они были обернуты observable.

MobX в сочетании с Preact формирует мощный инструмент для построения реактивных интерфейсов, позволяя управлять состоянием с минимальным кодом и высокой производительностью. Модель «обсерваблы — действия — вычисления — реакции» обеспечивает прозрачное и предсказуемое поведение приложения даже при сложной логике.