diff --git a/js_modules/dagster-ui/packages/ui-core/src/hooks/usePrevious.tsx b/js_modules/dagster-ui/packages/ui-core/src/hooks/usePrevious.tsx new file mode 100644 index 0000000000000..9fcdabd0cc842 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-core/src/hooks/usePrevious.tsx @@ -0,0 +1,9 @@ +import {useEffect, useRef} from 'react'; + +export const usePrevious = (value: T): T | undefined => { + const ref = useRef(); + useEffect(() => { + ref.current = value; + }, [value]); + return ref.current; +}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/selection/SelectionInput.tsx b/js_modules/dagster-ui/packages/ui-core/src/selection/SelectionInput.tsx index 3e013521b18be..683875ee8b2df 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/selection/SelectionInput.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/selection/SelectionInput.tsx @@ -12,6 +12,7 @@ import {SelectionAutoCompleteInputCSS} from './SelectionInputHighlighter'; import {useSelectionInputLintingAndHighlighting} from './useSelectionInputLintingAndHighlighting'; import {useTrackEvent} from '../app/analytics'; import {useDangerousRenderEffect} from '../hooks/useDangerousRenderEffect'; +import {usePrevious} from '../hooks/usePrevious'; import {useUpdatingRef} from '../hooks/useUpdatingRef'; import 'codemirror/addon/edit/closebrackets'; @@ -83,9 +84,23 @@ export const SelectionAutoCompleteInput = ({ const [selectedIndexRef, setSelectedIndex] = useState({current: 0}); + // Memoize the stringified results to avoid resetting the selected index down below + const resultsJson = useMemo(() => { + return JSON.stringify(autoCompleteResults?.list.map((l) => l.text)); + }, [autoCompleteResults]); + + const prevJson = usePrevious(resultsJson); + const prevAutoCompleteResults = usePrevious(autoCompleteResults); + + // Handle selection reset + useDangerousRenderEffect(() => { + if (prevAutoCompleteResults?.from !== autoCompleteResults?.from || prevJson !== resultsJson) { + selectedIndexRef.current = 0; + } + }, [resultsJson, autoCompleteResults, prevAutoCompleteResults, prevJson, selectedIndexRef]); + + // Handle hiding results useDangerousRenderEffect(() => { - // Rather then using a useEffect + setState (extra render), we just set the current value directly - selectedIndexRef.current = 0; if (!autoCompleteResults.list.length && !loading) { showResults.current = false; }