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

Реактивность и State

createState оборачивает объект в Proxy; мутации триггерят $subscribe.

$subscribe(callback) — подписка на изменения. Возвращает unsubscribe. Обычно callback = render:

const state = createState({ title: "Привет" });
function render() {
ui.render(Text(state.title));
}
// Подписываемся на изменения:
const unsubscribe = state.$subscribe(render);
// Вызываем для первоначального отображения:
render();
// Когда подписка больше не нужна (например, при выгрузке плагина):
// unsubscribe();

Вложенные объекты и массивы тоже реактивны — глубокие ключи и push/splice триггерят рендер:

const state = createState({
user: {
profile: { name: "Алексей" }
},
genres: ["Экшен", "Драма"]
});
// 1. Изменение глубоко вложенного свойства (автоматически вызовет рендер)
state.user.profile.name = "Иван";
// 2. Модификация массивов (добавление, удаление, сортировка)
state.genres.push("Комедия");
state.genres.splice(0, 1);

Синхронные мутации батчатся через Promise.resolve() — один вызов подписчика на такт:

const state = createState({ count: 0, lastAction: "none" });
state.$subscribe(() => {
console.log("Рендер вызван!");
});
// Синхронное изменение нескольких свойств:
state.count++;
state.lastAction = "increment";
state.count += 5;
// В консоли отобразится ровно ОДИН вывод "Рендер вызван!",
// так как все обновления объединились в один такт.

Счётчик с $subscribe:

const state = createState({ clicks: 0 });
function render() {
ui.render(
VStack()
.child(Text("Кликов: " + state.clicks))
.child(Button("Кликнуть").onClick(() => state.clicks++))
);
}

Запустить пример с реактивностью в Sandbox