ReviseAlgo Logo

Machine Coding

File Explorer

Master building a recursive File Explorer in React, covering tree data structures, expand/collapse toggling, folder creation, and immutable nested state updates.

Last Updated: July 15, 2026 14 min read

1. Learning Objectives

In this challenge, you will build a recursive File Explorer widget. By the end of this guide, you will be able to:

  • Model hierarchical file/folder data using nested tree structures.
  • Render recursive components that call themselves to display arbitrary nesting depths.
  • Toggle expand/collapse states on individual folder nodes.
  • Add new files and folders inside any level of the tree immutably.
  • Delete nodes from deeply nested structures without mutating state.

2. Overview

A File Explorer is one of the most popular machine coding interview questions. It tests your ability to work with recursive data structures, recursive component rendering, and immutable updates to deeply nested state objects. We will build a tree view with expand/collapse interactions, inline creation inputs, and delete operations.

3. Why This Challenge Matters

File explorers teach critical recursive programming patterns:

  • Recursive Component Design: A component rendering itself is a fundamental React pattern for tree-like UI structures (menus, org charts, comment threads).
  • Immutable Deep Updates: Updating a node buried five levels deep without mutating state forces you to master recursive mapping and spreading techniques.

4. Real-World Analogy

Think of building a File Explorer like organizing a physical filing cabinet:

  • Folders as Drawers: Each drawer (folder) can contain documents (files) or smaller organizer boxes (subfolders). Opening a drawer reveals its contents — this is the expand/collapse toggle.
  • Recursive Nesting: An organizer box inside a drawer can itself contain more boxes. The structure repeats at every level — this is why a recursive component works perfectly.
  • Adding Items: Slipping a new document into a specific drawer requires opening that exact drawer without disturbing other drawers — this is an immutable nested state update.

5. Core Concepts

Below is a comparison of flat list structures versus recursive tree structures:

Property Flat List Recursive Tree
Data Shape Array of objects: [{ id, name }] Object with children array: { id, name, children: [...] }
Rendering Single .map() call Component renders itself recursively for each children array
State Updates Simple filter/map on top-level array Recursive traversal to locate target node, then spread at every level
Use Case Todo lists, product catalogs File explorers, org charts, nested menus

6. Syntax & API Reference

This example shows the recursive tree node data structure and how a component renders itself:

7. Visual Diagram

This diagram illustrates how the recursive component renders itself for nested folder structures:

8. Live Example — Full Working Code

Below is a complete HTML page demonstrating a working file explorer with add and delete:

What just happened? The TreeNode component renders itself recursively for each child in the children array. The insertNode and deleteNode helper functions traverse the tree immutably to locate the target node and apply changes without mutating state.

9. Interactive Playground

Try It Yourself Challenges:

  1. Add a rename feature that lets the user double-click a file or folder name to edit it inline.
  2. Implement drag-and-drop to move files between folders.

10. Common Mistakes

Mistake Why it happens Wrong Correct
Mutating nested children directly Developers push new items into node.children directly, which mutates the original tree object and React does not detect the change. node.children.push(newItem);
setTree(tree);
setTree(prev =>
insertNode(prev, id, name));
Missing base case in recursion Forgetting to handle leaf nodes (files with no children) causes infinite recursion or crashes when the component tries to iterate over undefined. node.children.map(...) without checking if children exists isOpen && node.children &&
node.children.map(...)

11. Best Practices

  • Use helper functions for tree traversal: Create pure recursive helper functions like insertNode and deleteNode that return new tree objects instead of mutating in place.
  • Initialize children as empty arrays: Always initialize children: [] even for files. This avoids null checks throughout the recursive rendering logic.
  • Control expand state locally: Keep each node's expand/collapse state inside the TreeNode component itself rather than in a global state map, unless you need features like "expand all".
  • Use unique IDs: Generate unique IDs (e.g., Date.now().toString() or crypto.randomUUID()) for every node to serve as stable React keys.

12. Browser Compatibility/Requirements

This project runs on all modern browsers. No special APIs are required beyond standard JavaScript recursion and React state management.

13. Interview Questions

Q1: How do you update a deeply nested node in a tree structure immutably?

Answer: Write a recursive function that traverses the tree. At each level, use the spread operator to create a new object. When the target node is found, apply the modification and return the new object. The spread operator at every level ensures no ancestor objects are mutated.

Q2: Why is a recursive component the best approach for rendering tree structures?

Answer: Tree structures have arbitrary nesting depths that aren't known at compile time. A recursive component naturally mirrors the data structure: for each node, it renders itself for all children. This eliminates the need for complex flattening logic or manual depth tracking.

14. Debugging Exercise

Identify why clicking "Add File" inside a subfolder adds the file to the root instead:

View Solution

Diagnosis: The function never checks if tree.id === targetId. It always adds to the root's children array regardless of which folder was clicked.

Fix: Add a base case that checks the current node's ID:

15. Practice Exercises

Exercise 1: Search and highlight

Add a search input at the top of the file explorer. When the user types, auto-expand all folders containing matching file names and highlight the matching text in the file names.

16. Scenario-Based Challenge

The lazy-loaded file tree challenge:

You are building a file explorer for a cloud storage service with millions of files. Loading the entire tree upfront is not feasible. Design an approach where folder contents are fetched from an API only when the user expands a folder. Describe how you would handle loading states, error states, and caching already-fetched folder contents.

17. Quick Quiz

Q1: What is the base case for a recursive file explorer component?

A) When the component reaches the third nesting level

B) When the node is a file (has no children to render)

C) When the folder is collapsed

Answer: B — A file node has no children, so the recursion naturally stops. Collapsed folders also stop rendering children, but the true base case is the absence of children.

18. Summary & Key Takeaways

  • Model file systems as tree data structures with children arrays.
  • Use recursive components that render themselves for each child node.
  • Create pure recursive helper functions for immutable tree insert, delete, and update operations.
  • Keep expand/collapse state local to each TreeNode component instance.

19. Cheat Sheet

Operation Syntax Pattern
Recursive render node.children.map(c => <TreeNode node={c} />)
Immutable insert { ...tree, children: [newNode, ...tree.children] }
Immutable delete { ...tree, children: tree.children.filter(c => c.id !== id) }
---