A file browser ships on Friday. On Monday a PM files a ticket: “users can't select an entire folder — they have to tick every file one by one, which defeats the widget.” The engineer opens the component expecting a bug. There isn't one. The state is just a Set<string> that flips whichever id you toggle. It works for flat options (“favorite fruits?”), but stuffed into a tree, it's inert.
Below is the widget. Click the “Documents” folder and see what happens to the files inside. Then tick every file by hand and see what happens to “Documents”. Both probes reveal the same silent truth: the flat Set has no concept of a family.
Set<string>all empty// The flat version every first-pass ships.// No parent-child relationship. Every checkbox independent.function BrokenTreeSelect({ items }) { const [checked, setChecked] = useState(new Set()); const toggle = (id) => { const next = new Set(checked); next.has(id) ? next.delete(id) : next.add(id); setChecked(next); }; return ( <ul> {items.map((item) => ( <li key={item.id}> <input type="checkbox" checked={checked.has(item.id)} onChange={() => toggle(item.id)} /> {item.label} </li> ))} </ul> );}// What breaks:// 1. Clicking "Documents" checks only the "Documents" row.// No cascade to its files.// 2. Checking every file doesn't nudge "Documents" toward ticked.// 3. No concept of "some selected" — the parent either ticks (false)// or doesn't. The middle state is invisible.// 4. "Select all" needs a loop over every leaf. "Clear" needs// another. The parent checkbox is dead weight.Tick the “Documents” folder in the tree above. Watch the three files sitting below it. Before you peek — what do you expect?