We have learned about Mutation observer API
in our last blog(https://techcookies.com/post/mutation-observer-api), you can refer for basics and details.
In this blog we'll learn how we can implement it in ReactJS using TypeScript.
Mutation observer is an built-in JavaScript API that watch for changes made to the DOM tree and fires a callback function when it detects a change.
Mutation observer API
- useMutationObserver
import { useEffect, useRef } from 'react';
const options = {
attributes: true,
characterData: true,
childList: true,
subtree: true,
}
function useMutationObserver<T extends HTMLElement>(
callback: (target: T, options: MutationRecord) => void
) {
const ref = useRef<T>(null)
useEffect(() => {
const element = ref?.current;
if (!element) {
return;
}
const observer = new MutationObserver((entries: MutationRecord[]) => {
callback(element, entries[0]);
});
observer.observe(element, options);
return () => {
observer.disconnect();
};
}, [callback, ref]);
return ref
}
export default useMutationObserver;
"use client";
import { useCallback, useState } from "react";
import useMutationObserver from "../hooks/useMutationObserver";
const MutationObserverComp = () => {
const [width, setWidth] = useState("");
const [color, setColor] = useState("");
const [content, setContent] = useState("");
const onMutation = useCallback(
(target: HTMLDivElement, entry: MutationRecord) => {
if (entry.type === "attributes" && entry.attributeName === "style") {
switch (entry.target.clientHeight + 2) {
case 100:
// setColor("red");
target.style.backgroundColor = "white"
target.style.color = 'red';
target.textContent = "red";
break;
case 200:
target.style.backgroundColor = "green"
target.style.color = 'blue';
target.textContent = "blue";
break;
case 300:
target.style.backgroundColor = "red"
target.style.color = 'white';
target.textContent = "white";
break;
case 400:
target.style.backgroundColor = "blue"
target.style.color = 'yellow';
target.textContent = "yellow";
break;
default:
break;
}
}
},
[]
);
const ref = useMutationObserver(onMutation);
const clickHandler100 = () => {
setWidth("100px");
};
const clickHandler200 = () => {
setWidth("200px");
};
const clickHandler300 = () => {
setWidth("300px");
};
const clickHandler400 = () => {
setWidth("400px");
};
return (
<div>
<div
className="target-element"
ref={ref}
contentEditable
suppressContentEditableWarning={true}
style={{
width: width,
height: width,
backgroundColor: color,
border: "solid 1px black",
}}
>
{content}
</div>
<button
style={{ border: "solid 1px black", padding: "10px", margin: "10px" }}
onClick={clickHandler100}
>
100
</button>
<button
style={{ border: "solid 1px black", padding: "10px", margin: "10px" }}
onClick={clickHandler200}
>
200
</button>
<button
style={{ border: "solid 1px black", padding: "10px", margin: "10px" }}
onClick={clickHandler300}
>
300
</button>
<button
style={{ border: "solid 1px black", padding: "10px", margin: "10px" }}
onClick={clickHandler400}
>
400
</button>
</div>
);
};
export default MutationObserverComp;