Building a Nested Dropdown Menu in React with TypeScript
This challenge focuses on creating a reusable, nested dropdown menu component in React using TypeScript. Nested dropdowns are commonly used in applications with hierarchical data, such as category selection in e-commerce or organizational structures, providing a clean and intuitive user experience for navigating complex options. Your task is to build a component that can render a dropdown menu with multiple levels of nested options.
Problem Description
You need to create a React component called NestedDropdown that renders a dropdown menu with nested options. The component should accept a data structure representing the menu hierarchy as a prop. Each level of the hierarchy should be rendered as a dropdown, allowing users to navigate through the options.
Key Requirements:
- Data Structure: The component should accept a prop called
optionswhich is an array of objects. Each object represents a menu item and has the following structure:label: (string) The text to display for the menu item.children?: (NestedDropdownOptions[]) An optional array of objects representing the child menu items (nested dropdown). Ifchildrenis present, a nested dropdown will be rendered.value?: (any) An optional value associated with the menu item. This can be any data type.
- Rendering: The component should render a dropdown menu for each level of the hierarchy.
- State Management: The component should manage its own internal state to track the currently open dropdown level.
- Click Handling: Clicking on a menu item with children should open the corresponding nested dropdown. Clicking on a menu item without children should trigger an action (e.g., updating a state variable, calling a callback function - this is not required for this challenge, but consider it for future extensibility).
- Styling: Basic styling is expected to make the dropdown functional and visually understandable. You don't need to create a highly polished UI, but the dropdown should be clearly identifiable and usable.
Expected Behavior:
- When the component mounts, no dropdowns should be open by default.
- Clicking on a menu item with children should open the corresponding nested dropdown.
- Clicking on the same menu item again should close the nested dropdown.
- The dropdowns should be visually distinct and easy to navigate.
Edge Cases to Consider:
- Empty
optionsarray: The component should render nothing or a placeholder message. - Deeply nested menus: The component should handle menus with multiple levels of nesting without performance issues.
- Menu items with only text and no value.
Examples
Example 1:
Input:
options: [
{ label: 'Category 1', children: [
{ label: 'Subcategory 1.1', value: 'value1.1' },
{ label: 'Subcategory 1.2', value: 'value1.2' }
]},
{ label: 'Category 2', children: [
{ label: 'Subcategory 2.1', value: 'value2.1' },
{ label: 'Subcategory 2.2', value: 'value2.2' }
]}
]
Output:
A dropdown menu with two top-level options: "Category 1" and "Category 2". Clicking "Category 1" opens a dropdown with "Subcategory 1.1" and "Subcategory 1.2". Clicking "Category 2" opens a dropdown with "Subcategory 2.1" and "Subcategory 2.2".
Example 2:
Input:
options: [
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
{ label: 'Option 3', children: [
{ label: 'Suboption 3.1', value: 'suboption3.1' },
{ label: 'Suboption 3.2', value: 'suboption3.2' }
]}
]
Output:
A dropdown menu with three top-level options: "Option 1", "Option 2", and "Option 3". Clicking "Option 3" opens a dropdown with "Suboption 3.1" and "Suboption 3.2".
Example 3: (Edge Case)
Input:
options: []
Output:
(Nothing is rendered, or a message like "No options available")
Constraints
- Time Limit: You have 60 minutes to complete this challenge.
- Dependencies: You can only use React and TypeScript. No external libraries are allowed.
- Performance: The component should render efficiently, even with deeply nested menus (up to 5 levels deep).
- Code Quality: Write clean, readable, and well-documented code.
Notes
- Consider using recursion to render the nested dropdowns.
- Think about how to manage the state of the open/closed dropdowns efficiently.
- Focus on creating a functional and reusable component. Styling is secondary.
- Type safety is important. Leverage TypeScript to ensure the correctness of your code.
- The
valueproperty is optional and not required for the core functionality of the dropdown. It's included for potential future extensions. - Consider using a unique key prop for each menu item to improve React's rendering performance.