Home Dropdown manual with recursive method
Post
Cancel

Dropdown manual with recursive method

Creating a Recursive List Menu Any Number of Levels Deep

In this example, we’ll leverage recursion to build a menu that can have an unlimited number of nested levels.

  • And the result will looks like this:
  • result

Before diving into the task at hand, it is essential to establish the data type we are working with. Think about a scenario where we aim to display an image using a URL stored within the data. Without prior knowledge of the data structure, attempting to achieve this task would be impossible. Therefore, defining the data type is a fundamental prerequisite.

  • this is to say that: generics in ts does not help with this case that much. for data looks like :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 const items = [
    {
      title: "Item 1",
      subItem: [
        {
          title: "Item 1.1",
          subItem: [
            {
              title: "Item 1.1.1",
            },
          ],
        },
        {
          title: "Item 1.2",
        },
      ],
    },
  ];
  • the type should be :
1
2
3
4
interface SubItem {
  title: string;
  subItem?: SubItem[];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
interface DropdownListProps<T> {
  items: T[];
}

const DropdownItem = ({ item }: DropdownItemProps) => {
  const [isOpen, setIsOpen] = useState(false);

  const handleMouseEnter = () => {
    setIsOpen(true);
  };

  const handleMouseLeave = () => {
    setIsOpen(false);
  };

  return (
    <div
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      style=
    >
      {item.title}
      {Array.isArray(item?.subItem) && isOpen && (
        <div
          style=
        >
          {item.subItem.map((childItem) => (
            <DropdownItem key={childItem.title} item={childItem} />
          ))}
        </div>
      )}
    </div>
  );
};

function DropdownList<T extends SubItem>({ items }: DropdownListProps<T>) {
  return (
    <div>
      {items.map((item) => (
        <DropdownItem key={item.title} item={item} />
      ))}
    </div>
  );
}
export default DropdownList;
  • in the code, we will check the type of item.subItem with Array.isArray(item?.subItem), if it is an array, we will proceed the recursion function ` {item.subItem.map((childItem) => ( <DropdownItem key={childItem.title} item={childItem} /> ))}`.

  • that is how to implement the recursion method to create an dropdown list.
  • further improvement(TODOS:): considering accessibility and keyboard events
This post is licensed under CC BY 4.0 by the author.