Skip to content
Observe

useObserveIgnorable

Runs a reactive effect with an ignoreUpdates escape hatch. Changes made inside ignoreUpdates(updater) do not trigger the effect. Useful for breaking circular update cycles in two-way bindings.

useObserveIgnorable
Listening

Update the source normally or inside ignoreUpdates to suppress the effect.

(no effect fired yet)
import {
import useObserveIgnorable
useObserveIgnorable
,
import useObservable
useObservable
} from "@usels/web";
function
function Component(): void
Component
() {
const
const source$: any
source$
=
import useObservable
useObservable
(0);
const {
const ignoreUpdates: any
ignoreUpdates
,
const isIgnoring$: any
isIgnoring$
} =
import useObserveIgnorable
useObserveIgnorable
(
() =>
const source$: any
source$
.
any
get
(),
(
value: any
value
) => {
any
console
.
any
log
("source changed:",
value: any
value
);
}
);
// Normal change — effect fires
const source$: any
source$
.
any
set
(1);
// Ignored change — effect is suppressed
const ignoreUpdates: any
ignoreUpdates
(() => {
const source$: any
source$
.
any
set
(2);
});
}

The primary use case is preventing a reactive feedback loop when syncing two observables.

import { useObserveIgnorable, useObservable, useWatch } from "@usels/web";
function Component() {
const local$ = useObservable("");
const remote$ = useObservable("");
// Sync remote → local without triggering local → remote
const { ignoreUpdates } = useObserveIgnorable(
() => remote$.get(),
(remoteValue) => {
ignoreUpdates(() => {
local$.set(remoteValue);
});
}
);
// Sync local → remote
useWatch(
() => local$.get(),
(localValue) => {
remote$.set(localValue);
}
);
}

isIgnoring$ is an Observable that reflects whether an ignoreUpdates call is currently active.

import { observable, Show, useObserveIgnorable } from "@usels/web";
const count$ = useObservable(0);
function MyComponent() {
const { ignoreUpdates, isIgnoring$ } = useObserveIgnorable(
() => count$.get(),
(value) => {
console.log("count:", value);
}
);
return (
<Show if={isIgnoring$}>
<span>Ignoring updates...</span>
</Show>
);
}

Pass immediate: true to execute the effect immediately on setup.

import { useObserveIgnorable, useObservable } from "@usels/web";
function Component() {
const count$ = useObservable(0);
const { ignoreUpdates } = useObserveIgnorable(
() => count$.get(),
(value) => {
console.log("value:", value);
},
{ immediate: true }
);
}
export { observeIgnorable, type ObserveIgnorableReturn } from "./core";
export type UseObserveIgnorable = typeof observeIgnorable;
/**
* Runs a reactive effect with an `ignoreUpdates` escape hatch to suppress circular triggers.
*
* Built on `watch` — lazy by default (`immediate: false`).
* Changes made inside `ignoreUpdates(updater)` do not trigger the effect.
* Useful for two-way bindings where you need to break update cycles.
*
* @param selector - Observable, array of Observables, or reactive read function.
* @param effect - Side-effect callback. Suppressed when triggered via `ignoreUpdates`.
* @param options - `{ immediate?, schedule? }`
* @returns `{ ignoreUpdates, isIgnoring$, dispose }`
*
* @example
* ```tsx twoslash
* // @noErrors
* import { useObserveIgnorable } from "@usels/core";
* import { observable } from "@legendapp/state";
*
* const source$ = observable(0);
*
* const { ignoreUpdates, isIgnoring$ } = useObserveIgnorable(
* () => source$.get(),
* (value) => { console.log("source:", value); }
* );
*
* // Update source without triggering the effect
* ignoreUpdates(() => { source$.set(42); });
* ```
*/
export declare const useObserveIgnorable: UseObserveIgnorable;

View on GitHub