Skip to content
Observe

useObserveWithFilter

Runs a reactive effect gated by an EventFilter. The selector always tracks dependencies on every change; only the effect execution is controlled by the filter.

import {
import createPausableFilter
createPausableFilter
,
import useObservable
useObservable
,
import useObserveWithFilter
useObserveWithFilter
} from "@usels/web";
function
function Component(): void
Component
() {
const
const count$: any
count$
=
import useObservable
useObservable
(0);
const {
const pause: any
pause
,
const resume: any
resume
,
const eventFilter: any
eventFilter
} =
import createPausableFilter
createPausableFilter
();
// ✅ Effect only fires when the filter allows it
import useObserveWithFilter
useObserveWithFilter
(
() =>
const count$: any
count$
.
any
get
(),
(
value: any
value
) => {
any
console
.
any
log
("count:",
value: any
value
);
},
{
eventFilter: any
eventFilter
}
);
}

Control when the effect fires by pausing and resuming the filter. The selector continues tracking changes in the background.

import { createPausableFilter, useObservable, useObserveWithFilter } from "@usels/web";
function Component() {
const count$ = useObservable(0);
const { pause, resume, eventFilter } = createPausableFilter();
useObserveWithFilter(
() => count$.get(),
(value) => {
console.log("updated:", value);
},
{ eventFilter }
);
// ✅ Pause the filter — changes to count$ won't trigger the effect
pause();
// ✅ Resume — the effect fires again on changes
resume();
}

Use a debounce filter to only execute the effect after the source stops changing for a specified duration.

import { createDebounceFilter, useObservable, useObserveWithFilter } from "@usels/web";
function Component() {
const query$ = useObservable("");
useObserveWithFilter(
() => query$.get(),
(value) => {
console.log("search:", value);
},
{ eventFilter: createDebounceFilter(300) }
);
}

Pass immediate: true to execute the effect immediately on setup, in addition to triggering on source changes.

import { createPausableFilter, useObservable, useObserveWithFilter } from "@usels/web";
function Component() {
const count$ = useObservable(0);
const { eventFilter } = createPausableFilter();
// ✅ Also executes the effect immediately with the initial value
useObserveWithFilter(
() => count$.get(),
(value) => {
console.log("value:", value);
},
{ eventFilter, immediate: true }
);
}

The schedule option controls when the effect runs relative to Legend-State’s batch cycle.

  • schedule: 'sync' — runs synchronously inside the batch (equivalent to Legend-State immediate: true)
  • schedule: 'deferred' — runs after the batch ends (equivalent to Legend-State immediate: false)
  • omitted — uses Legend-State’s default batching
useObserveWithFilter(count$, (v) => console.log(v), { eventFilter, schedule: "sync" });
export { observeWithFilter, type ObserveWithFilterOptions } from "./core";
export type UseObserveWithFilter = typeof observeWithFilter;
/**
* Runs a reactive effect through an EventFilter, controlling when the effect fires.
*
* Built on `watch` — lazy by default (`immediate: false`), with full `WatchOptions` support.
* The selector always tracks deps on every change; only the effect is gated by the filter.
*
* @param selector - Observable, array of Observables, or reactive read function.
* @param effect - Side-effect callback. Execution is controlled by `eventFilter`.
* @param options - `{ eventFilter, immediate?, schedule? }`
*
* @example
* ```tsx twoslash
* // @noErrors
* import { useObserveWithFilter, createPausableFilter } from "@usels/core";
* import { observable } from "@legendapp/state";
*
* const count$ = observable(0);
* const { pause, resume, eventFilter } = createPausableFilter();
*
* useObserveWithFilter(
* () => count$.get(),
* (value) => { console.log("count:", value); },
* { eventFilter }
* );
* ```
*/
export declare const useObserveWithFilter: UseObserveWithFilter;

View on GitHub