From 3df4576ceeadaf2a28eced33ac2fa24b52056800 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sat, 5 Jul 2025 02:11:41 +0200 Subject: [PATCH] Fix Downshift autocomplete behavior --- CHANGELOG.md | 1 + src/components/FieldSourceLayer.tsx | 1 - src/components/InputAutocomplete.tsx | 41 ++++++---------------------- 3 files changed, 9 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73d4892c..c78fa3c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Remove react-autobind dependency - Remove usage of legacy `childContextTypes` API - Replace react-autocomplete with Downshift in the autocomplete component +- Simplify autocomplete component and fix dropdown flicker when clicking - _...Add new stuff here..._ ### 🐞 Bug fixes diff --git a/src/components/FieldSourceLayer.tsx b/src/components/FieldSourceLayer.tsx index d17da5a3..832ce98d 100644 --- a/src/components/FieldSourceLayer.tsx +++ b/src/components/FieldSourceLayer.tsx @@ -29,7 +29,6 @@ class FieldSourceLayerInternal extends React.Component [l, l])} diff --git a/src/components/InputAutocomplete.tsx b/src/components/InputAutocomplete.tsx index f84c927c..370383f4 100644 --- a/src/components/InputAutocomplete.tsx +++ b/src/components/InputAutocomplete.tsx @@ -2,14 +2,10 @@ import React from 'react' import classnames from 'classnames' import {useCombobox} from 'downshift' - -const MAX_HEIGHT = 140; - export type InputAutocompleteProps = { value?: string options?: any[] onChange?(value: string | undefined): unknown - keepMenuWithinWindowBounds?: boolean 'aria-label'?: string }; @@ -17,12 +13,9 @@ export default function InputAutocomplete({ value, options = [], onChange = () => {}, - keepMenuWithinWindowBounds, 'aria-label': ariaLabel, }: InputAutocompleteProps) { - const [maxHeight, setMaxHeight] = React.useState(MAX_HEIGHT) const [input, setInput] = React.useState(value || '') - const autocompleteMenuEl = React.useRef(null) const filteredItems = React.useMemo(() => { const lv = input.toLowerCase() @@ -40,18 +33,21 @@ export default function InputAutocomplete({ items: filteredItems, inputValue: input, itemToString: (item) => (item ? item[0] : ''), + stateReducer: (_state, action) => { + if (action.type === useCombobox.stateChangeTypes.InputClick) { + return {...action.changes, isOpen: true} + } + return action.changes + }, onSelectedItemChange: ({selectedItem}) => { const v = selectedItem ? selectedItem[0] : '' setInput(v) onChange(selectedItem ? selectedItem[0] : undefined) }, - onInputValueChange: ({inputValue: v, type}) => { + onInputValueChange: ({inputValue: v}) => { if (typeof v === 'string') { setInput(v) onChange(v === '' ? undefined : v) - if (type === useCombobox.stateChangeTypes.InputChange) { - openMenu() - } } }, }) @@ -60,23 +56,8 @@ export default function InputAutocomplete({ setInput(value || '') }, [value]) - const calcMaxHeight = React.useCallback(() => { - if (keepMenuWithinWindowBounds && autocompleteMenuEl.current) { - const maxHeightLocal = window.innerHeight - - autocompleteMenuEl.current.getBoundingClientRect().top - const limitedMaxHeight = Math.min(maxHeightLocal, MAX_HEIGHT) - if (limitedMaxHeight !== maxHeight) { - setMaxHeight(limitedMaxHeight) - } - } - }, [keepMenuWithinWindowBounds, maxHeight]) - - React.useEffect(() => { - calcMaxHeight() - }) - return ( -
+