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$} />;}import { createRef$ } from "@usels/core";import { createMutationObserver } from "@usels/web";
function Component() { "use scope" const el$ = createRef$<HTMLDivElement>();
createMutationObserver( el$, (records) => { records.forEach((r) => { /* handle r.type, r.target */ }); }, { attributes: true, childList: true } );
return <div ref={el$} />;}Watching attributes only
Section titled “Watching attributes only”useMutationObserver(el$, callback, { attributes: true });createMutationObserver(el$, callback, { attributes: true });Filtering specific attributes
Section titled “Filtering specific attributes”Only fire when aria-expanded or data-active change:
useMutationObserver(el$, callback, { attributes: true, attributeFilter: ["aria-expanded", "data-active"],});createMutationObserver(el$, callback, { attributes: true, attributeFilter: ["aria-expanded", "data-active"],});Recording the previous attribute value
Section titled “Recording the previous attribute value”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 });createMutationObserver( 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 });Watching descendant nodes with subtree
Section titled “Watching descendant nodes with subtree”useMutationObserver(el$, callback, { childList: true, subtree: true });createMutationObserver(el$, callback, { childList: true, subtree: true });Multiple targets
Section titled “Multiple targets”useMutationObserver([el$, anotherEl], callback, { attributes: true });createMutationObserver([el$, anotherEl], callback, { attributes: true });Stop and resume
Section titled “Stop and resume”const { stop, resume } = useMutationObserver(el$, callback, { childList: true });
stop(); // disconnects the observerresume(); // reconnects with the same target and optionsconst { stop, resume } = createMutationObserver(el$, callback, { childList: true });
stop(); // disconnects the observerresume(); // reconnects with the same target and optionsFlushing pending records
Section titled “Flushing pending records”const { takeRecords } = useMutationObserver(el$, callback, { attributes: true });
const pending = takeRecords();const { takeRecords } = createMutationObserver(el$, callback, { attributes: true });
const pending = takeRecords();Checking browser support
Section titled “Checking browser support”const { isSupported$ } = useMutationObserver(el$, callback, { attributes: true });
console.log(isSupported$.get()); // Observable<boolean>const { isSupported$ } = createMutationObserver(el$, callback, { attributes: true });
console.log(isSupported$.get()); // Observable<boolean>Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
target | MaybeEventTarget | MaybeEventTarget[] | - |
callback | MutationCallback | - |
options | UseMutationObserverOptions (optional) | - |
UseMutationObserverOptions
Section titled “UseMutationObserverOptions”Returns
Section titled “Returns”UseMutationObserverReturn
| Name | Type | Description |
|---|---|---|
isActive$ | ReadonlyObservable<boolean> | - |
stop | () => void | - |
resume | () => void | - |
takeRecords | () => MutationRecord[] | - |
isSupported$ | ReadonlyObservable<boolean> | - |