Build an Accessible Recursive Expand-and-Collapse Tree in React
Company: Apple
Role: Frontend Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
# Build an Accessible Recursive Expand-and-Collapse Tree in React
Implement a React component that renders hierarchical data with `+` and `-` controls for collapsed and expanded nodes.
```javascript
const data = {
id: 1,
name: "Root",
children: [
{
id: 2,
name: "Child 1",
children: [
{ id: 3, name: "Child 1.1" },
{ id: 4, name: "Child 1.2" }
]
},
{ id: 5, name: "Child 2" }
]
};
```
Nodes with children have an interactive control; leaf nodes do not. Expansion state must be independent per node and remain stable when another branch toggles. Explain component decomposition, state representation, recursion, keys, and accessibility.
### Constraints & Assumptions
- Node IDs are unique and stable.
- A missing or empty `children` array means the node is a leaf.
- The initial state may be all collapsed except the visible root row.
- The component need not fetch children remotely for the base problem.
### Clarifying Questions to Ask
- Should expansion be controlled by a parent, local to the tree, or persisted in the URL/storage?
- Are full keyboard tree-view semantics required or is a nested-list disclosure UI sufficient?
- Can the data update while branches are expanded?
- How deep and large can the tree become?
### What a Strong Answer Covers
- A `Set` or map keyed by stable node ID
- Immutable toggle updates and recursive rendering
- Semantic buttons, accessible names, and `aria-expanded`
- Stable keys and leaf handling
- Tests for branch independence, updates, and keyboard use
### Follow-up Questions
- How would you support lazy-loaded children?
- What happens to expansion state when a node is removed?
- How would you virtualize a very large expanded tree?
- When should expansion state be lifted out of the component?
Quick Answer: Implement an accessible recursive React tree whose expandable branches keep independent state as users toggle other nodes. The exercise covers stable IDs and keys, immutable state updates, leaf behavior, semantic buttons, aria-expanded, keyboard use, data changes, and scaling to deep trees.