Фреймворк Fresh для JavaScript и Deno предоставляет современный подход к построению реактивных веб-приложений с минимальной зависимостью от клиентского JavaScript. Одной из ключевых концепций является подписка на изменения данных, которая позволяет автоматически обновлять интерфейс при изменении состояния без явного вмешательства разработчика.
В основе механизма подписки лежат сигналы
(Signal). Сигналы представляют собой объекты, которые
хранят текущее значение и уведомляют подписчиков при его изменении. Они
используются для создания реактивного состояния компонентов.
Пример создания сигнала:
import { signal } from "@preact/signals";
const count = signal(0);
count.value — текущее значение сигнала.count.value = новое_значение
автоматически уведомляет все подписанные компоненты.Сигналы позволяют строить одностороннюю реактивность, где UI всегда синхронизирован с состоянием без ручного обновления.
Подписка на изменения сигнала осуществляется с помощью метода
.subscribe():
const unsubscribe = count.subscribe((newValue) => {
console.log("Новое значение count:", newValue);
});
subscribe принимает колбэк, который вызывается при
каждом изменении значения сигнала.unsubscribe позволяет прекратить
подписку, что важно для управления памятью в больших приложениях.Подписка может быть использована для:
Для работы с побочными эффектами используется функция
effect. Она автоматически подписывается на все сигналы,
которые используются внутри неё, и вызывается при их изменении.
import { effect } from "@preact/signals";
effect(() => {
console.log("Текущее значение count:", count.value);
});
effect,
становятся зависимостями.Сигналы можно комбинировать для создания производных значений:
import { computed } from "@preact/signals";
const doubleCount = computed(() => count.value * 2);
effect(() => {
console.log("Двойное значение count:", doubleCount.value);
});
computed создает производное значение,
которое пересчитывается только при изменении зависимых сигналов.В Fresh подписка на изменения данных интегрирована напрямую в JSX через сигналы:
export default function Counter() {
const count = signal(0);
return (
<div>
<p>Счётчик: {count}</p>
<button onCl ick={() => count.value++}>Увеличить</button>
</div>
);
}
count.value автоматически перерисовывает
текст внутри <p>.useState или других хуков,
как в классическом React.Для сложных сценариев важно контролировать время жизни подписок, чтобы избежать утечек памяти. В Fresh можно использовать эффекты с очисткой:
import { effect } from "@preact/signals";
effect((cleanup) => {
const interval = setInterval(() => count.value++, 1000);
cleanup(() => clearInterval(interval));
});
cleanup вызывается при размонтировании эффекта или
компонента.Подписка на внешние источники данных, такие как WebSocket или API, реализуется через сигналы:
import { signal, effect } from "@preact/signals";
const messages = signal([]);
const ws = new WebSocket("wss://example.com/chat");
ws.onmess age = (event) => {
messages.value = [...messages.value, event.data];
};
effect(() => {
console.log("Сообщения:", messages.value);
});
computed для фильтрации или
агрегации данных.computed.effect, всегда
учитывая очистку ресурсов.Механизм подписки на изменения в Fresh обеспечивает простую, прозрачную и эффективную реактивность, позволяя строить динамические интерфейсы без лишней сложности и большого объема клиентского кода.