From 6de23362321ec4d50abdd8c16eef7af2beffb956 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Mon, 1 Dec 2025 10:34:33 +0000 Subject: [PATCH] convert NestedFolderList --- .../NestedFolderPicker/NestedFolderList.tsx | 111 +++++++----------- 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx index 7e53679f84e..f89d8b39512 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderList.tsx @@ -1,9 +1,9 @@ import { css, cx } from '@emotion/css'; -import { useCallback, useId, useMemo, useRef } from 'react'; +import { useCallback, useId, useRef } from 'react'; import * as React from 'react'; import Skeleton from 'react-loading-skeleton'; -import { FixedSizeList as List } from 'react-window'; -import InfiniteLoader from 'react-window-infinite-loader'; +import { List, type RowComponentProps } from 'react-window'; +import { useInfiniteLoader } from 'react-window-infinite-loader'; import { GrafanaTheme2 } from '@grafana/data'; import { Trans } from '@grafana/i18n'; @@ -47,32 +47,8 @@ export function NestedFolderList({ requestLoadMore, emptyFolders, }: NestedFolderListProps) { - const infiniteLoaderRef = useRef(null); const styles = useStyles2(getStyles); - const virtualData = useMemo( - (): VirtualData => ({ - items, - focusedItemIndex, - foldersAreOpenable, - selectedFolder, - onFolderExpand, - onFolderSelect, - idPrefix, - emptyFolders, - }), - [ - items, - focusedItemIndex, - foldersAreOpenable, - selectedFolder, - onFolderExpand, - onFolderSelect, - idPrefix, - emptyFolders, - ] - ); - const handleIsItemLoaded = useCallback( (itemIndex: number) => { return isItemLoaded(itemIndex); @@ -81,36 +57,42 @@ export function NestedFolderList({ ); const handleLoadMore = useCallback( - (startIndex: number, endIndex: number) => { + async (startIndex: number, endIndex: number) => { const { parentUID } = items[startIndex]; requestLoadMore(parentUID); }, [requestLoadMore, items] ); + const onRowsRendered = useInfiniteLoader({ + rowCount: items.length, + isRowLoaded: handleIsItemLoaded, + loadMoreRows: handleLoadMore, + }); + return (
{items.length > 0 ? ( - - {({ onItemsRendered, ref }) => ( - - {Row} - - )} - + ) : (
No folders found @@ -122,25 +104,20 @@ export function NestedFolderList({ interface VirtualData extends Omit {} -interface RowProps { - index: number; - style: React.CSSProperties; - data: VirtualData; -} - const SKELETON_WIDTHS = [100, 200, 130, 160, 150]; -function Row({ index, style: virtualStyles, data }: RowProps) { - const { - items, - focusedItemIndex, - foldersAreOpenable, - selectedFolder, - onFolderExpand, - onFolderSelect, - idPrefix, - emptyFolders, - } = data; +function Row({ + index, + style: virtualStyles, + items, + focusedItemIndex, + foldersAreOpenable, + selectedFolder, + onFolderExpand, + onFolderSelect, + idPrefix, + emptyFolders, +}: RowComponentProps) { const { item, isOpen, level, parentUID } = items[index]; const rowRef = useRef(null); const labelId = useId(); @@ -190,7 +167,9 @@ function Row({ index, style: virtualStyles, data }: RowProps) { Non-folder {{ itemKind }} {{ itemUID }} - ) : null; + ) : ( + <> + ); } // We don't have a direct value of whether things are coming from user searching but this seems to be a good