useMutationObserver
Hook to use Mutation Observer.
See: Mutation Observer API.
Demo
INFO
The component has an ul element and two button to add and remove li childs. The cbRef callback returned from useMutationObserver hook is attached to ul element, so then ul childs change, the callback passed to hook update messages state variable with added and removed nodes.
Loading demo…
Show source code
tsx
import { useState } from "react"
import { useMutationObserver } from "../../../.."
export const UseMutationObserver = () => {
const [messages, setMessages] = useState<string[]>([]);
const [data, setData] = useState<string[]>([]);
const { ref, disconnect, reconnect } = useMutationObserver<HTMLUListElement>(
mutations => {
for (const mutation of mutations) {
const arr: string[] = [];
mutation.addedNodes.forEach(node => arr.push(`Added node: ${node.textContent}`));
mutation.removedNodes.forEach(node => arr.push(`Removed node: ${node.textContent}`));
setMessages(m => m.concat(arr));
}
},
{ mode: "ref" },
{
childList: true,
subtree: true
}
)
return <div>
<button onClick={() => setData(d => [...d, d.length.toString()])}>ADD child</button>
<button onClick={() => setData(d => d.filter((_, index) => index !== d.length - 1))}>Remove child</button>
<button onClick={reconnect}>Reconnect</button>
<button onClick={disconnect}>Disconnect</button>
<div style={{ display: "grid", gridTemplateColumns: "auto auto", gap: 50 }}>
<div>
<ul ref={ref}>
{
data.map(el => <li key={el}>Item {el}</li>)
}
</ul>
</div>
<div>
{
messages.map(el => <p>{el}</p>)
}
</div>
</div>
</div>
}Types
UseMutationObserverProps
@templateT - The element type observed by the {@link MutationObserver}.
Parameters accepted by useMutationObserver.
| Property | Type | Required | Description |
|---|---|---|---|
cb | MutationCallback | ✓ | The {@link MutationCallback} invoked whenever a mutation matching the configured opts is detected on the observed element. Receives the array of {@link MutationRecord} objects and the observer instance itself. |
attachOptions | \| { mode: "ref"; targetRef?: never } \| { mode: "effect" \| "layout-effect"; targetRef: RefObject<T> } | ✓ | Controls how the target element is attached to the observer: - { mode: "ref" } — The hook returns a RefCallback to attach directly to the JSX element. The observer is connected when the ref is set. - { mode: "effect", targetRef } — The observer is connected inside a useEffect using the provided RefObject. - { mode: "layout-effect", targetRef } — The observer is connected inside a useLayoutEffect using the provided RefObject, running synchronously before the browser paints. |
opts | MutationObserverInit | Options forwarded to the {@link MutationObserver} constructor. Controls which types of mutations are observed (childList, attributes, characterData, subtree, etc.). When omitted, the observer uses the browser defaults. |
UseMutationObserverResult
@templateT - The element type observed by the {@link MutationObserver}.
Return value of useMutationObserver.
| Property | Type | Required | Description |
|---|---|---|---|
ref | RefCallback<T> \| null | ✓ | A React ref callback to attach to the target element. Only populated when attachOptions.mode is "ref" — null in "effect" and "layout-effect" modes where the target is provided via targetRef instead. |
disconnect | () => void | ✓ | Disconnects the observer, stopping all mutation notifications. The observer can be restarted by calling {@link UseMutationObserverResult.reconnect}. |
reconnect | () => void | ✓ | Reconnects the observer after it has been disconnected, resuming mutation notifications for the target element. |
takeRecords | () => MutationRecord[] | ✓ | Empties the observer's record queue and returns an array of {@link MutationRecord} objects describing all mutations that have been detected but not yet delivered to the callback. Useful for flushing pending mutations before disconnecting. |
