10 Lines of Code: The Flat-to-Tree Algorithm Every Frontend Dev Needs
This pattern — flat storage, tree display — is the default in nearly every relational database-backed web app. Mastering the O(n) conversion means you stop writing recursive lookups that accidentally hit O(n²). It's a tiny piece of code that saves hours of debugging nested data.
When a backend runs `select * from menu`, the result is a flat array of items with a `parentId` field. But frontend components like Ant Design's Tree or Element UI's Cascader expect nested objects with a `children` array. The gap is universal in admin dashboards, address pickers, and org charts.
The solution is a two-pass algorithm. First, build an index mapping each id to its node (with an empty children array). Second, iterate again: for each node, look up its parent by parentId and push the node into that parent's children. Nodes with parentId 0 become roots. The Map version uses ES6 Map for O(1) lookups; the reduce version uses a plain object and functional style. Both run in O(n) time and O(n) space.
The key insight is that parentId is the "DNA" of the tree — it encodes the hierarchy without nesting. The algorithm simply resolves that encoding into a structure the DOM can render. A debugging bonus: `JSON.stringify(tree, null, 2)` prints the result with clean indentation.
The algorithm is a practical example of 'space for time' — building an index upfront eliminates nested lookups.
The two-pass structure is generalizable: any problem that involves resolving references (like graph edges) can use the same pattern.
The reduce version is more elegant but less obvious to debug; the Map version is clearer for teams new to functional programming.
Most frontend developers overcomplicate this with recursion when a simple linear pass suffices.
The same pattern works for any hierarchical data: categories, comments, org charts, file systems.