Переключение вниз: установите для inputValue значение текущего выделенного элемента при навигации по клавиатуре - PullRequest
0 голосов
/ 06 апреля 2020

Используя Downshift, как можно реализовать установление inputValue к значению выделенного в данный момент элемента в ArrowUp / ArrowDown при сохранении отфильтрованных элементов до тех пор, пока пользователь вручную не увеличит inputValue?

Например:

Google Typeahead example

1 Ответ

0 голосов
/ 06 апреля 2020

Вышеупомянутое поведение может быть реализовано с использованием хука stateReducer и useCombobox и следующим образом:

import React, { useState } from "react";
import { render } from "react-dom";
import { useCombobox } from "downshift";
import { items, menuStyles } from "./utils";

function stateReducer(state, actionAndChanges) {
  switch (actionAndChanges.type) {
    case useCombobox.stateChangeTypes.InputChange:
      return {
        ...actionAndChanges.changes,
        userInput: actionAndChanges.changes.inputValue
      };
    case useCombobox.stateChangeTypes.InputKeyDownArrowDown:
    case useCombobox.stateChangeTypes.InputKeyDownArrowUp:
      if (!actionAndChanges.changes.inputValue) return actionAndChanges.changes;

      return {
        ...actionAndChanges.changes,
        userInput: actionAndChanges.changes.inputValue,
        inputValue: actionAndChanges.getItemNodeFromIndex(
          actionAndChanges.changes.highlightedIndex
        ).innerText
      };
    default:
      return actionAndChanges.changes; // otherwise business as usual.
  }
}

function DropdownSelect() {
  const [inputItems, setInputItems] = useState(items);
  const {
    isOpen,
    getToggleButtonProps,
    getLabelProps,
    getMenuProps,
    getInputProps,
    getComboboxProps,
    highlightedIndex,
    getItemProps
  } = useCombobox({
    items: inputItems,
    stateReducer,
    onInputValueChange: ({ userInput, inputValue }) => {
      if (userInput === inputValue) {
        const filteredItems = items.filter(item =>
          item.toLowerCase().startsWith(inputValue.toLowerCase())
        );
        setInputItems(filteredItems);
      }
    }
  });

  return (
    <React.Fragment>
      <label {...getLabelProps()}>Choose an element:</label>
      <div style={{ display: "inline-block" }} {...getComboboxProps()}>
        <input {...getInputProps()} />
        <button {...getToggleButtonProps()} aria-label="toggle menu">
          &#8595;
        </button>
      </div>
      <ul {...getMenuProps()} style={menuStyles}>
        {isOpen &&
          inputItems.map((item, index) => (
            <li
              style={
                highlightedIndex === index ? { backgroundColor: "#bde4ff" } : {}
              }
              key={`${item}${index}`}
              {...getItemProps({ item, index })}
            >
              {item}
            </li>
          ))}
      </ul>
    </React.Fragment>
  );
}

render(<DropdownSelect />, document.getElementById("root"));

Просмотреть изолированную программную среду кода здесь

...