Using Downshift with Nested Arrays for Typeahead Functionality

28 views Asked by At

I'm attempting to implement a typeahead functionality using the Downshift package in my React application. In my current setup, I'm encountering an issue where I cannot select "List 2" because it conflicts with the index of "List 3." Additionally, hovering over the list highlights the incorrect list item due to the lack of custom index management.

Is there a solution to this problem, or is Downshift the appropriate package for this use case?

const categories: Category[] = [
  {
    name: "Category 1",
    lists: [
      { id: 1, name: "List 1" },
      { id: 2, name: "List 2" },
    ],
  },
  {
    name: "Category 2",
    lists: [{ id: 3, name: "List 3" }],
  },
];

const ExampleComponent = ({ categories }: ExampleComponentProps) => (
  <Downshift
    onChange={(selection) => console.log(`You selected ${selection.name}`)}
    itemToString={(item) => (item ? item.name : "")}
  >
    {({
      getLabelProps,
      getInputProps,
      getMenuProps,
      getItemProps,
      setHighlightedIndex,
      isOpen,
      inputValue,
      highlightedIndex,
      selectedItem,
    }) => (
      <div>
        <label {...getLabelProps()}>Select a list:</label>
        <input {...getInputProps()} />
        <ul {...getMenuProps()}>
          {isOpen
            ? categories
                .filter(
                  (category) =>
                    !inputValue ||
                    category.name
                      .toLowerCase()
                      .includes(inputValue.toLowerCase())
                )
                .map((category) => (
                  <Fragment key={category.name}>
                    <p>{category.name}</p>
                    <ul>
                      {category.lists.map((list, index) => (
                        <li
                          {...getItemProps({
                            key: list.id,
                            index: index,
                            item: list,
                            highlightedIndex,
                          })}
                          style={{
                            backgroundColor:
                              highlightedIndex === index &&
                              selectedItem !== list
                                ? "lightgray"
                                : "white",
                            fontWeight:
                              selectedItem === list ? "bold" : "normal",
                          }}
                        >
                          {list.name}
                        </li>
                      ))}
                    </ul>
                  </Fragment>
                ))
            : null}
        </ul>
      </div>
    )}
  </Downshift>
);
0

There are 0 answers