Skip to content

useCombobox: HighlightedIndex and Items are not in sync #1623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
christinaheidt opened this issue Aug 28, 2024 · 3 comments · May be fixed by #1631
Closed

useCombobox: HighlightedIndex and Items are not in sync #1623

christinaheidt opened this issue Aug 28, 2024 · 3 comments · May be fixed by #1631
Labels

Comments

@christinaheidt
Copy link

  • downshift version: 9.0.7
  • node version: 20.9.0
  • yarn version: 4.4.0

Relevant code or config

  const [inputItems, setInputItems] = useState(items)
  const {
    isOpen,
    getToggleButtonProps,
    getLabelProps,
    getMenuProps,
    getInputProps,
    highlightedIndex,
    getItemProps,
  } = useCombobox({
    items: inputItems,
    isItemDisabled: (item) => item.length > 10,
    defaultHighlightedIndex: 0,
    onInputValueChange: ({inputValue}) => {
      setInputItems(
        items.filter((item) =>
          item.toLowerCase().startsWith(inputValue.toLowerCase()),
        ),
      )
    },
  })

What you did:

  • Added a defaultHighlightedIndex: 0
  • Added a isItemDisabled method

What happened:
The highlightedIndex is always one step behind the item list. E.g. when searching for a disabled item the first time the list gets reduced to just that item but the highlighted index is still at value 0 instead of being -1. Furthermore when searching for a value that doesn't exist in the list the application will run into an exception with the second update:
image

combobox

Reproduction repository:
https://codesandbox.io/p/sandbox/musing-williams-jwq6vz?file=%2Fsrc%2Fhooks%2FuseCombobox%2Fbasic-usage.js&moduleview=-1

Problem description:
See what happened

Suggested solution:
The items and the index should update at the same time

@Bluebberies
Copy link

  • downshift version: 9.0.7
  • node version: 20.9.0
  • yarn version: 4.4.0

Relevant code or config

  const [inputItems, setInputItems] = useState(items)
  const {
    isOpen,
    getToggleButtonProps,
    getLabelProps,
    getMenuProps,
    getInputProps,
    highlightedIndex,
    getItemProps,
  } = useCombobox({
    items: inputItems,
    isItemDisabled: (item) => item.length > 10,
    defaultHighlightedIndex: 0,
    onInputValueChange: ({inputValue}) => {
      setInputItems(
        items.filter((item) =>
          item.toLowerCase().startsWith(inputValue.toLowerCase()),
        ),
      )
    },
  })

What you did:

  • Added a defaultHighlightedIndex: 0
  • Added a isItemDisabled method

What happened: The highlightedIndex is always one step behind the item list. E.g. when searching for a disabled item the first time the list gets reduced to just that item but the highlighted index is still at value 0 instead of being -1. Furthermore when searching for a value that doesn't exist in the list the application will run into an exception with the second update: image

combobox combobox

Reproduction repository: https://codesandbox.io/p/sandbox/musing-williams-jwq6vz?file=%2Fsrc%2Fhooks%2FuseCombobox%2Fbasic-usage.js&moduleview=-1

Problem description: See what happened

Suggested solution: The items and the index should update at the same time

All you need to do is to update your own code in these areas;

change this

{isOpen && inputItems.map((item, index) => ( <li style={{ backgroundColor: highlightedIndex === index ? '#bde4ff' : '', opacity: isItemDisabled(item) ? 0.3 : 1, }} key={${item}${index}} {...getItemProps({item, index})} > {item} </li> ))}

to this

{isOpen && inputItems.length > 0 && inputItems.map((item, index) => ( <li style={{ backgroundColor: highlightedIndex === index ? '#bde4ff' : '', opacity: isItemDisabled(item) ? 0.3 : 1, }} key={${item}${index}} {...getItemProps({item, index})} > {item} </li> ))}

and also update the isItemDisabled function to this

const isItemDisabled = (item) => item && item.length > 10;

@silviuaavram
Copy link
Collaborator

I hope @Bluebberies comment solved it, @christinaheidt . Closing.

@KrzysztofKarol
Copy link

KrzysztofKarol commented Jan 3, 2025

@silviuaavram shouldn't the typings be fixed?

-isItemDisabled?(item: Item, index: number): boolean
+isItemDisabled?(item: Item | undefined, index: number): boolean

isItemDisabled?(item: Item, index: number): boolean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants