Two lists, one keyed by name and one by index, are reversed. Which rows keep their state, and which <li> elements does React move?
Both lists render the same teas with the same Row, which keeps a liked flag in its own state. The first list uses each tea's name as the key, the second its index. A MutationObserver, set up after the first render, logs every <li> that React inserts into either list, including one it moves.
import { useEffect, useRef, useState } from "react";
function Row({ name }) {
const [liked, setLiked] = useState(false);
return (
<li>
{name}
{liked ? " (liked)" : ""}{" "}
<button onClick={() => setLiked(true)}>Like {name}</button>
</li>
);
}
export default function App() {
const [teas, setTeas] = useState(["Green", "Black", "Mint"]);
const byName = useRef(null);
const byIndex = useRef(null);
useEffect(() => {
const observer = new MutationObserver((records) => {
for (const record of records) {
for (const li of record.addedNodes) {
console.log(record.target.getAttribute("aria-label") + ": inserted " + li.firstChild.data);
}
}
});
observer.observe(byName.current, { childList: true });
observer.observe(byIndex.current, { childList: true });
return () => observer.disconnect();
}, []);
return (
<>
<ul ref={byName} aria-label="By name">
{teas.map((tea) => (
<Row key={tea} name={tea} />
))}
</ul>
<ul ref={byIndex} aria-label="By index">
{teas.map((tea, index) => (
<Row key={index} name={tea} />
))}
</ul>
<button onClick={() => setTeas([...teas].reverse())}>Reverse</button>
</>
);
}
It runs in development, rendered as <App />, and then:
- You click Like Green in the list keyed by name.
- You click Like Green in the list keyed by index.
- You click Reverse.
The answer
Work out every line it logs, in order, and what the page shows at the end. Then check.
Checking your sign-in…