Skip to content
Elements

useMutationObserver

Reactive wrapper around the MutationObserver API. Observes one or more DOM nodes for mutations — attribute changes, child additions/removals, and text content changes. Targets can be Ref$, MaybeElement, or a plain Element.

Mutation Observer
observing
data-active: children: 0
— no mutations recorded yet
import {
const useRef$: {
<T = any>(initialValue: null): Ref$<T | null>;
<T = any>(initialValue: T): Ref$<T>;
<T = any>(): Ref$<T | null>;
}
useRef$
} from "@usels/core";
import {
const useMutationObserver: (target: MaybeEventTarget | MaybeEventTarget[], callback: MutationCallback, options?: DeepMaybeObservable<UseMutationObserverOptions>) => UseMutationObserverReturn
useMutationObserver
} from "@usels/web";
function
function Component(): JSX.Element
Component
() {
const
const el$: Ref$<HTMLDivElement | null>
el$
=
useRef$<HTMLDivElement>(): Ref$<HTMLDivElement | null> (+2 overloads)

Core (framework-agnostic) version of useRef$. Creates an observable element ref with opaque wrapping.

  • non-null value → Ref$<T>: current, get(), peek() return T
  • null / no arg → Ref$<T | null>: current, get(), peek() return T | null

Nullability is expressed via the type parameter, mirroring T | null at the call site.

useRef$
<
interface HTMLDivElement
HTMLDivElement
>();
function useMutationObserver(target: MaybeEventTarget | MaybeEventTarget[], callback: MutationCallback, options?: DeepMaybeObservable<UseMutationObserverOptions>): UseMutationObserverReturn
useMutationObserver
(
const el$: Ref$<HTMLDivElement | null>
el$
,
(
records: any
records
) => {
records: any
records
.
any
forEach
((
r: any
r
) => {
/* handle r.type, r.target */
});
},
{
attributes: boolean
attributes
: true,
childList: boolean
childList
: true }
);
return <
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
RefAttributes<HTMLDivElement>.ref?: Ref<HTMLDivElement> | undefined

Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).

ref
={
const el$: Ref$<HTMLDivElement | null>
el$
} />;
}
useMutationObserver(el$, callback, { attributes: true });

Only fire when aria-expanded or data-active change:

useMutationObserver(el$, callback, {
attributes: true,
attributeFilter: ["aria-expanded", "data-active"],
});
useMutationObserver(
el$,
(records) => {
records.forEach((r) => {
const next = (r.target as Element).getAttribute(r.attributeName!);
console.log("old:", r.oldValue, "→ new:", next);
});
},
{ attributes: true, attributeOldValue: true }
);
useMutationObserver(el$, callback, { childList: true, subtree: true });
useMutationObserver([el$, anotherEl], callback, { attributes: true });
const { stop, resume } = useMutationObserver(el$, callback, { childList: true });
stop(); // disconnects the observer
resume(); // reconnects with the same target and options
const { takeRecords } = useMutationObserver(el$, callback, { attributes: true });
const pending = takeRecords();
const { isSupported$ } = useMutationObserver(el$, callback, { attributes: true });
console.log(isSupported$.get()); // Observable<boolean>
ParameterTypeDescription
targetMaybeEventTarget | MaybeEventTarget[]-
callbackMutationCallback-
optionsUseMutationObserverOptions (optional)-
OptionTypeDefaultDescription
attributeFilterstring[]-Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed and attributes is true or omitted.
attributeOldValueboolean-Set to true if attributes is true or omitted and target’s attribute value before the mutation needs to be recorded.
attributesboolean-Set to true if mutations to target’s attributes are to be observed. Can be omitted if attributeOldValue or attributeFilter is specified.
characterDataboolean-Set to true if mutations to target’s data are to be observed. Can be omitted if characterDataOldValue is specified.
characterDataOldValueboolean-Set to true if characterData is set to true or omitted and target’s data before the mutation needs to be recorded.
childListboolean-Set to true if mutations to target’s children are to be observed.
subtreeboolean-Set to true if mutations to not just target, but also target’s descendants are to be observed.

UseMutationObserverReturn

NameTypeDescription
isActive$ReadonlyObservable<boolean>-
stop() => void-
resume() => void-
takeRecords() => MutationRecord[]-
isSupported$ReadonlyObservable<boolean>-

View on GitHub