import { useState, useEffect, useRef } from "react";
import "./styles.css";
const weak = new WeakMap();
let i = 0;
const unique = () => i++;
export default function App() {
const ref = useRef(null);
const [arr, setArr] = useState([0, 1, 2]);
useEffect(() => {
if (ref.current) {
for (const child of [...ref.current.children]) {
if (weak.has(child)) {
// print its value
console.log(
"Seen: ",
child,
" assigned random number: ",
weak.get(child)
);
} else {
console.log(
"New DOM element: ",
child,
" with value: ",
child.textContent
);
weak.set(child, unique());
}
}
}
});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setArr((prev) => [prev.length, ...prev])}>
Action
</button>
<ul ref={ref}>
{arr.map((key) => (
<li key={key}>{key}</li>
))}
</ul>
</div>
);
}
By using a WeakMap and a HTMLCollection we can track each DOM element added by React. In this case assign an strictly increasing number to it. If we have seen it already, then just print out that it has been seen before, and the number assigned to it.
I am using the HTMLCollection by accessing the children property on the `ul` element. If you store this orthogonality to React, that means out of any life cycle bounds, you'll see this list changing because it is a live collection, and when the DOM mutates so does the HTMLCollection. It is not super essential for the snippet above, but I think you might want to explore further. A MutationObserver, a weakMap and the live HTMLCollection could be used to build a widget that shows the newly added DOM elements, presumably added by React.
Good question! You got a bunch of people surprised.
Here's a codesandbox to get started ASAP: https://codesandbox.io/s/currying-morning-m1oop
And some logs:
// initial render
New DOM element: <li>0</li> with value: 0
New DOM element: <li>1</li> with value: 1
New DOM element: <li>2</li> with value: 2
// after clicking action button
New DOM element: <li>3</li> with value: 3
Seen: <li>0</li> assigned random number: 0
Seen: <li>1</li> assigned random number: 1
Seen: <li>2</li> assigned random number: 2