Skip to content

once

Пропускает только первое срабатывание, остальные глотает — пока необязательный reset не взведёт его заново.

ts
once(source);
once(source, { reset });

Возвращает Event<T> — и для события-источника, и для стора.

Онбординг и разовые баннеры

ts
import { once } from "@virentia/core/utils";

const firstOpen = once(appOpened);

reaction({ on: firstOpen, run: () => showOnboarding() });

Флаг «уже было» внутри once — это стор: он живёт в своём скоупе и попадает в SSR-снапшот. Онбординг, показанный при серверном рендере, не мигнёт второй раз после гидрации. В этом весь смысл оператора: соблазнительный самодельный вариант с let fired = false на уровне модуля заводит флаг на весь процесс — SSR-запрос одного пользователя помечает «показано» сразу всем.

Аналитика первого использования

Событие «фичу попробовали» — ровно один раз на сессию:

ts
const featureTried = once(exportClicked);

reaction({ on: featureTried, run: () => void trackFx("export-first-use") });

Ленивый прогрев

Загрузить тяжёлые данные при первом открытии панели — и только при первом:

ts
const panelFirstOpened = once(panelOpened);

reaction({ on: panelFirstOpened, run: () => void preloadHistoryFx() });

Взвести заново

reset превращает «однажды» в «однажды за эпоху» — за сессию, за документ:

ts
const greeted = once(sessionStarted, { reset: loggedOut });

После loggedOut следующий sessionStarted в том же скоупе снова пройдёт.

Когда пригодится

  • Всё, что показывается или отправляется только в первый раз: онбординг, подсказки, аналитика знакомства с фичей, прогрев данных.
  • С reset — «первый раз для каждой сущности или сессии»: перевзвод по выходу из аккаунта, смене документа, открытию новой записи.

Когда не подходит: если условие на самом деле состояние («пользователь прошёл настройку?») — заведите стор и computed. once — про сам факт первого раза, а не про долгоживущий булев флаг.

Поведение

  • Флаг у каждого скоупа свой: скоуп A, поймавший первое срабатывание, не глушит скоуп B.
  • Как стор, флаг участвует в сериализации скоупа — это сделано специально, см. случай с онбордингом.
  • Dispose владельца снимает подписки оператора, как у любой реакции.