diff --git a/.changeset/calm-jeans-ring.md b/.changeset/calm-jeans-ring.md new file mode 100644 index 0000000000..3d1efcf7bd --- /dev/null +++ b/.changeset/calm-jeans-ring.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Use virtualization with `EntityPicker` as done earlier with `MultiEntityPicker` to fix performance issues with large data sets. `VirtualizedListbox` extracted into reusable component. diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 176f6e9ce0..9eca3e85c5 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -43,6 +43,7 @@ import { EntityPickerUiOptions, EntityPickerFilterQuery, } from './schema'; +import { VirtualizedListbox } from '../VirtualizedListbox'; export { EntityPickerSchema } from './schema'; @@ -205,6 +206,7 @@ export const EntityPicker = (props: EntityPickerProps) => { entities?.entityRefToPresentation.get(stringifyEntityRef(option)) ?.primaryTitle!, })} + ListboxComponent={VirtualizedListbox} /> ); diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx index 84a050622a..d800c9b372 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx @@ -35,7 +35,6 @@ import Autocomplete, { AutocompleteChangeReason, } from '@material-ui/lab/Autocomplete'; import React, { useCallback, useEffect } from 'react'; -import { FixedSizeList, ListChildComponentProps } from 'react-window'; import useAsync from 'react-use/esm/useAsync'; import { FieldValidation } from '@rjsf/utils'; import { @@ -44,41 +43,10 @@ import { MultiEntityPickerUiOptions, MultiEntityPickerFilterQuery, } from './schema'; +import { VirtualizedListbox } from '../VirtualizedListbox'; export { MultiEntityPickerSchema } from './schema'; -const renderRow = (props: ListChildComponentProps) => { - const { data, index, style } = props; - return React.cloneElement(data[index], { style }); -}; - -const ListboxComponent = React.forwardRef< - HTMLDivElement, - { children?: React.ReactNode } ->((props, ref) => { - const itemData = React.Children.toArray(props.children); - const itemCount = itemData.length; - - const itemSize = 36; - - const itemsToShow = Math.min(10, itemCount); - const height = Math.max(itemSize, itemsToShow * itemSize - 0.5 * itemSize); - - return ( -