Katkat

Build an Accessible Recursive Expand-and-Collapse Tree in React

AppleFrontend Engineer · Technical Screen

Last updated

This problem tests recursive component design in React, state management for nested data structures, and the implementation of WAI-ARIA standards for accessible UI components.

Building an Accessible Tree Component

Implement a reusable Tree component in React that renders a nested data structure. The tree should allow users to toggle the expansion of nodes, where each node maintains its own independent open/closed state.

Requirements

  1. Data Structure: Assume the data is an array of objects where each node has id, label, and an optional children array.
  2. Accessibility: Use semantic HTML (e.g., `` for toggles) and appropriate ARIA attributes (aria-expanded, role="treeitem") to ensure screen-reader compatibility.
  3. Keyboard Interaction: The toggle should be focusable and interactive via the Enter/Space keys.
  4. Performance: Ensure stable React keys are used to prevent unnecessary re-renders when toggling deeply nested nodes.

Input Data Format

[
  {
    "id": "1",
    "label": "Root",
    "children": [
      { "id": "2", "label": "Child A" },
      { "id": "3", "label": "Child B", "children": [{ "id": "4", "label": "Grandchild" }] }
    ]
  }
]

Function Signature

// Example component usage

Edge Cases

  • Empty tree data.
  • Nodes with no children (leaves) should not show an expand toggle.
  • Very deep trees (ensure the component does not crash or cause performance bottlenecks).

Hints

Hint 1

Use a recursive functional component approach where the component calls itself if a node contains a children array.

Hint 2

Store the expansion state of nodes in an object (a dictionary) where keys are node IDs to avoid prop drilling and maintain state independently.

Hint 3

Ensure the `aria-expanded` attribute is dynamically updated based on the state of that specific node's ID.

Follow-up questions

  • How would you optimize the component if the tree contained 10,000+ nodes to prevent browser UI freezing?
  • How would you implement a 'Collapse All' feature that resets the state of all nodes simultaneously?
  • If this tree were controlled by a parent component, how would you prevent unnecessary re-renders of non-toggled branches?