diff --git a/src/renderer/components/virtual-grid/grid-card/default-card.module.css b/src/renderer/components/virtual-grid/grid-card/default-card.module.css deleted file mode 100644 index c2d7d7bad..000000000 --- a/src/renderer/components/virtual-grid/grid-card/default-card.module.css +++ /dev/null @@ -1,98 +0,0 @@ -.container { - display: flex; - flex-direction: column; - width: 100%; - height: calc(100% - 2rem); - overflow: hidden; - pointer-events: auto; - cursor: pointer; - border-radius: var(--theme-radius-md); - - &:hover { - background: var(--theme-colors-surface-hover); - } -} - -.container.is-hidden { - opacity: 0; -} - -.inner-container { - display: flex; - flex-direction: column; - width: 100%; - height: 100%; - padding: 1rem; - overflow: hidden; - background: lighten(var(--theme-colors-surface), 3%); - - .card-controls { - opacity: 0; - } - - &:hover .card-controls { - opacity: 1; - } - - &:hover * { - &::before { - opacity: 0.5; - } - } -} - -.image-container { - position: relative; - display: flex; - align-items: center; - height: 100%; - aspect-ratio: 1/1; - overflow: hidden; - - &::before { - position: absolute; - top: 0; - left: 0; - z-index: 1; - width: 100%; - height: 100%; - user-select: none; - content: ''; - background: linear-gradient(0deg, rgb(0 0 0 / 100%) 35%, rgb(0 0 0 / 0%) 100%); - opacity: 0; - transition: all 0.2s ease-in-out; - } -} - -.image-container.is-favorite { - &::after { - position: absolute; - top: -50px; - left: -50px; - width: 80px; - height: 80px; - pointer-events: none; - content: ''; - background-color: var(--theme-colors-primary-filled); - box-shadow: 0 0 10px 8px rgb(0 0 0 / 80%); - transform: rotate(-45deg); - } -} - -.image { - width: 100%; - max-width: 100%; - height: 100% !important; - max-height: 100%; - border: 0; - border-radius: var(--theme-radius-md); - - img { - height: 100%; - object-fit: var(--theme-image-fit); - } -} - -.detail-container { - margin-top: 0.5rem; -} diff --git a/src/renderer/components/virtual-grid/grid-card/default-card.tsx b/src/renderer/components/virtual-grid/grid-card/default-card.tsx deleted file mode 100644 index b337952ea..000000000 --- a/src/renderer/components/virtual-grid/grid-card/default-card.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import clsx from 'clsx'; -import { useState } from 'react'; -import { generatePath, useNavigate } from 'react-router-dom'; -import { ListChildComponentProps } from 'react-window'; - -import styles from './default-card.module.css'; - -import { CardRows } from '/@/renderer/components/card/card-rows'; -import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls'; -import { Image } from '/@/shared/components/image/image'; -import { Skeleton } from '/@/shared/components/skeleton/skeleton'; -import { Stack } from '/@/shared/components/stack/stack'; -import { - Album, - AlbumArtist, - Artist, - LibraryItem, - Playlist, - Song, -} from '/@/shared/types/domain-types'; -import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types'; - -interface BaseGridCardProps { - columnIndex: number; - controls: { - cardRows: CardRow[]; - handleFavorite: (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => void; - handlePlayQueueAdd: (options: PlayQueueAddOptions) => void; - itemGap: number; - itemType: LibraryItem; - playButtonBehavior: Play; - resetInfiniteLoaderCache: () => void; - route: CardRoute; - }; - data: any; - isHidden?: boolean; - listChildProps: Omit; -} - -export const DefaultCard = ({ - columnIndex, - controls, - data, - isHidden, - listChildProps, -}: BaseGridCardProps) => { - const navigate = useNavigate(); - - const [isHovered, setIsHovered] = useState(false); - - if (data) { - const path = generatePath( - controls.route.route as string, - controls.route.slugs?.reduce((acc, slug) => { - return { - ...acc, - [slug.slugProperty]: data[slug.idProperty], - }; - }, {}), - ); - - return ( -
navigate(path)} - onMouseEnter={() => setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - style={{ - margin: controls.itemGap, - }} - > -
-
- - -
-
- -
-
-
- ); - } - - return ( -
-
-
- -
-
- - {(controls?.cardRows || []).map((row, index) => ( - - ))} - -
-
-
- ); -}; diff --git a/src/renderer/components/virtual-grid/grid-card/grid-card-controls.module.css b/src/renderer/components/virtual-grid/grid-card/grid-card-controls.module.css deleted file mode 100644 index 5a7c3a467..000000000 --- a/src/renderer/components/virtual-grid/grid-card/grid-card-controls.module.css +++ /dev/null @@ -1,84 +0,0 @@ -.play-button { - position: absolute; - display: flex; - align-items: center; - justify-content: center; - width: 50px; - height: 50px; - background-color: var(--theme-colors-white); - border: none; - border-radius: 50%; - opacity: 0.8; - transition: opacity 0.2s ease-in-out; - transition: scale 0.1s ease-in-out; - - &:hover { - background-color: var(--theme-colors-white); - opacity: 1; - } - - &:active { - opacity: 1; - } - - svg { - fill: var(--theme-colors-black); - stroke: var(--theme-colors-black); - } -} - -.secondary-button { - opacity: 0.8; - transition: opacity 0.2s ease-in-out; - transition: scale 0.2s linear; - - &:hover { - opacity: 1; - } - - &:active { - opacity: 1; - } -} - -.grid-card-controls-container { - position: absolute; - z-index: 100; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; -} - -.favorite-banner { - position: absolute; - top: -50px; - left: -50px; - width: 80px; - height: 80px; - pointer-events: none; - content: ''; - background-color: var(--theme-colors-primary-filled); - box-shadow: 0 0 10px 8px rgb(0 0 0 / 80%); - transform: rotate(-45deg); -} - -.favorite-wrapper { - svg { - fill: var(--theme-colors-primary-filled); - } -} - -.bottom-controls { - position: absolute; - bottom: 0; - display: flex; - gap: var(--theme-spacing-md); - align-items: flex-end; - justify-content: flex-end; - width: 100%; - height: calc(100% / 3); - padding: 1rem 0.5rem; -} diff --git a/src/renderer/components/virtual-grid/grid-card/grid-card-controls.tsx b/src/renderer/components/virtual-grid/grid-card/grid-card-controls.tsx deleted file mode 100644 index 206bdd1a2..000000000 --- a/src/renderer/components/virtual-grid/grid-card/grid-card-controls.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import clsx from 'clsx'; -import { MouseEvent, useState } from 'react'; - -import styles from './grid-card-controls.module.css'; - -import { - ALBUM_CONTEXT_MENU_ITEMS, - ARTIST_CONTEXT_MENU_ITEMS, - PLAYLIST_CONTEXT_MENU_ITEMS, -} from '/@/renderer/features/context-menu/context-menu-items'; -import { useHandleGridContextMenu } from '/@/renderer/features/context-menu/hooks/use-handle-context-menu'; -import { usePlayerContext } from '/@/renderer/features/player/context/player-context'; -import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; -import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; -import { Button } from '/@/shared/components/button/button'; -import { Icon } from '/@/shared/components/icon/icon'; -import { LibraryItem } from '/@/shared/types/domain-types'; -import { Play } from '/@/shared/types/types'; - -export const GridCardControls = ({ - handleFavorite, - isHovered, - itemData, - itemType, - resetInfiniteLoaderCache, -}: { - handleFavorite: (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - serverId: string; - }) => void; - isHovered?: boolean; - itemData: any; - itemType: LibraryItem; - resetInfiniteLoaderCache?: () => void; -}) => { - const [isFavorite, setIsFavorite] = useState(itemData?.userFavorite); - const playButtonBehavior = usePlayButtonBehavior(); - - const player = usePlayerContext(); - - const handlePlay = async (e: MouseEvent, playType?: Play) => { - e.preventDefault(); - e.stopPropagation(); - - player.addToQueueByFetch( - itemData._serverId, - [itemData.id], - itemType, - playType || playButtonBehavior, - ); - }; - - const handleFavorites = async (e: MouseEvent, serverId: string) => { - e.preventDefault(); - e.stopPropagation(); - - handleFavorite?.({ - id: [itemData.id], - isFavorite: itemData.userFavorite, - itemType, - serverId, - }); - - setIsFavorite(!isFavorite); - }; - - const handleContextMenu = useHandleGridContextMenu( - itemType, - itemType === LibraryItem.ALBUM - ? ALBUM_CONTEXT_MENU_ITEMS - : itemType === LibraryItem.PLAYLIST - ? PLAYLIST_CONTEXT_MENU_ITEMS - : ARTIST_CONTEXT_MENU_ITEMS, - resetInfiniteLoaderCache, - ); - - return ( - <> - {isFavorite ?
: null} - {isHovered && ( -
- -
- {itemType !== LibraryItem.PLAYLIST && ( - handleFavorites(e, itemData?.serverId)} - size="sm" - variant="transparent" - /> - )} - { - e.preventDefault(); - e.stopPropagation(); - handleContextMenu(e, [itemData]); - }} - size="sm" - variant="transparent" - /> -
-
- )} - - ); -}; diff --git a/src/renderer/components/virtual-grid/grid-card/index.tsx b/src/renderer/components/virtual-grid/grid-card/index.tsx deleted file mode 100644 index 5749dca19..000000000 --- a/src/renderer/components/virtual-grid/grid-card/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import type { ListChildComponentProps } from 'react-window'; - -import { memo } from 'react'; -import { areEqual } from 'react-window'; - -import { DefaultCard } from '/@/renderer/components/virtual-grid/grid-card/default-card'; -import { PosterCard } from '/@/renderer/components/virtual-grid/grid-card/poster-card'; -import { CardRow, GridCardData, ListDisplayType } from '/@/shared/types/types'; - -export const GridCard = memo(({ data, index, style }: ListChildComponentProps) => { - const { - cardRows, - columnCount, - display, - handleFavorite, - handlePlayQueueAdd, - itemCount, - itemData, - itemGap, - itemType, - playButtonBehavior, - resetInfiniteLoaderCache, - route, - } = data as GridCardData; - - const cards: React.ReactNode[] = []; - const startIndex = index * columnCount; - const stopIndex = Math.min(itemCount - 1, startIndex + columnCount - 1); - - const columnCountInRow = stopIndex - startIndex + 1; - let columnCountToAdd = 0; - if (columnCountInRow !== columnCount) { - columnCountToAdd = columnCount - columnCountInRow; - } - const View = display === ListDisplayType.CARD ? DefaultCard : PosterCard; - - for (let i = startIndex; i <= stopIndex + columnCountToAdd; i += 1) { - cards.push( - [], - handleFavorite, - handlePlayQueueAdd, - itemGap, - itemType, - playButtonBehavior, - resetInfiniteLoaderCache, - route, - }} - data={itemData[i]} - isHidden={i > stopIndex} - key={`card-${i}-${index}`} - listChildProps={{ index }} - />, - ); - } - - return ( -
- {cards} -
- ); -}, areEqual); diff --git a/src/renderer/components/virtual-grid/grid-card/poster-card.module.css b/src/renderer/components/virtual-grid/grid-card/poster-card.module.css deleted file mode 100644 index 1755bbe17..000000000 --- a/src/renderer/components/virtual-grid/grid-card/poster-card.module.css +++ /dev/null @@ -1,90 +0,0 @@ -.container { - display: flex; - flex-direction: column; - width: 100%; - height: 100%; - overflow: hidden; - pointer-events: auto; - - &:global(.card-controls) { - opacity: 0; - } -} - -.container.hidden { - opacity: 0; -} - -.link-container { - cursor: pointer; -} - -.image-container { - position: relative; - display: flex; - align-items: center; - aspect-ratio: 1/1; - overflow: hidden; - - &::before { - position: absolute; - top: 0; - left: 0; - z-index: 1; - width: 100%; - height: 100%; - user-select: none; - content: ''; - background: linear-gradient(0deg, rgb(0 0 0 / 100%) 35%, rgb(0 0 0 / 0%) 100%); - opacity: 0; - transition: all 0.2s ease-in-out; - } - - &:hover { - &::before { - opacity: 0.5; - } - } - - &:hover .card-controls { - opacity: 1; - } -} - -.image-container.is-favorite { - &::after { - position: absolute; - top: -50px; - left: -50px; - width: 80px; - height: 80px; - pointer-events: none; - content: ''; - background-color: var(--theme-colors-primary-filled); - box-shadow: 0 0 10px 8px rgb(0 0 0 / 80%); - transform: rotate(-45deg); - } -} - -.image { - width: 100%; - max-width: 100%; - height: 100% !important; - max-height: 100%; - border: 0; - border-radius: var(--theme-radius-md); - - img { - height: 100%; - object-fit: var(--theme-image-fit); - } -} - -.detail-container { - margin-top: 0.5rem; -} - -.placeholder-wrapper { - width: 100%; - height: 100%; -} diff --git a/src/renderer/components/virtual-grid/grid-card/poster-card.tsx b/src/renderer/components/virtual-grid/grid-card/poster-card.tsx deleted file mode 100644 index fb8d5befc..000000000 --- a/src/renderer/components/virtual-grid/grid-card/poster-card.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import clsx from 'clsx'; -import { useState } from 'react'; -import { generatePath, useNavigate } from 'react-router-dom'; -import { ListChildComponentProps } from 'react-window'; - -import styles from './poster-card.module.css'; - -import { CardRows } from '/@/renderer/components/card/card-rows'; -import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls'; -import { Image } from '/@/shared/components/image/image'; -import { Skeleton } from '/@/shared/components/skeleton/skeleton'; -import { Stack } from '/@/shared/components/stack/stack'; -import { - Album, - AlbumArtist, - Artist, - LibraryItem, - Playlist, - Song, -} from '/@/shared/types/domain-types'; -import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types'; - -interface BaseGridCardProps { - columnIndex: number; - controls: { - cardRows: CardRow[]; - handleFavorite: (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => void; - handlePlayQueueAdd: (options: PlayQueueAddOptions) => void; - itemGap: number; - itemType: LibraryItem; - playButtonBehavior: Play; - resetInfiniteLoaderCache: () => void; - route: CardRoute; - }; - data: any; - isHidden?: boolean; - listChildProps: Omit; -} - -export const PosterCard = ({ - columnIndex, - controls, - data, - isHidden, - listChildProps, -}: BaseGridCardProps) => { - const navigate = useNavigate(); - - const [isHovered, setIsHovered] = useState(false); - - if (data) { - const path = generatePath( - controls.route.route as string, - controls.route.slugs?.reduce((acc, slug) => { - return { - ...acc, - [slug.slugProperty]: data[slug.idProperty], - }; - }, {}), - ); - - return ( -
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - style={{ - margin: controls.itemGap, - }} - > -
navigate(path)}> -
- - -
-
-
- -
-
- ); - } - - return ( -
-
- -
-
- - {(controls?.cardRows || []).map((row, index) => ( - - ))} - -
-
- ); -}; diff --git a/src/renderer/components/virtual-grid/virtual-grid-wrapper.module.css b/src/renderer/components/virtual-grid/virtual-grid-wrapper.module.css deleted file mode 100644 index 50563d0b7..000000000 --- a/src/renderer/components/virtual-grid/virtual-grid-wrapper.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.virtual-grid-container { - display: flex; - flex-direction: column; - height: 100%; -} - -.virtual-grid-auto-sizer-container { - flex: 1; -} diff --git a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx b/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx deleted file mode 100644 index 820b37e1d..000000000 --- a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import type { - CardRoute, - CardRow, - ListDisplayType, - PlayQueueAddOptions, -} from '/@/shared/types/types'; -import type { Ref } from 'react'; -import type { FixedSizeListProps } from 'react-window'; - -import debounce from 'lodash/debounce'; -import memoize from 'memoize-one'; -import { FixedSizeList } from 'react-window'; - -import styles from './virtual-grid-wrapper.module.css'; - -import { GridCard } from '/@/renderer/components/virtual-grid/grid-card'; -import { Album, AlbumArtist, Artist, LibraryItem } from '/@/shared/types/domain-types'; - -const createItemData = memoize( - ( - cardRows, - columnCount, - display, - itemCount, - itemData, - itemGap, - itemHeight, - itemType, - itemWidth, - route, - handlePlayQueueAdd, - handleFavorite, - resetInfiniteLoaderCache, - ) => ({ - cardRows, - columnCount, - display, - handleFavorite, - handlePlayQueueAdd, - itemCount, - itemData, - itemGap, - itemHeight, - itemType, - itemWidth, - resetInfiniteLoaderCache, - route, - }), -); - -const createScrollHandler = memoize((onScroll) => debounce(onScroll, 250)); - -export const VirtualGridWrapper = ({ - cardRows, - columnCount, - display, - handleFavorite, - handlePlayQueueAdd, - height, - initialScrollOffset, - itemCount, - itemData, - itemGap, - itemHeight, - itemType, - itemWidth, - onScroll, - refInstance, - resetInfiniteLoaderCache, - route, - rowCount, - width, - ...rest -}: Omit & { - cardRows: CardRow[]; - columnCount: number; - display: ListDisplayType; - handleFavorite?: (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => void; - handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void; - height?: number; - itemData: any[]; - itemGap: number; - itemHeight: number; - itemType: LibraryItem; - itemWidth: number; - refInstance: Ref; - resetInfiniteLoaderCache: () => void; - route?: CardRoute; - rowCount: number; - width?: number; -}) => { - const memoizedItemData = createItemData( - cardRows, - columnCount, - display, - itemCount, - itemData, - itemGap, - itemHeight, - itemType, - itemWidth, - route, - handlePlayQueueAdd, - handleFavorite, - resetInfiniteLoaderCache, - ); - - const memoizedOnScroll = createScrollHandler(onScroll); - - return ( - - {GridCard} - - ); -}; - -interface VirtualGridContainerProps { - children: React.ReactNode; -} - -export const VirtualGridContainer = ({ children }: VirtualGridContainerProps) => { - return
{children}
; -}; - -export const VirtualGridAutoSizerContainer = ({ children }: VirtualGridContainerProps) => { - return
{children}
; -}; diff --git a/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx b/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx deleted file mode 100644 index 4263439d3..000000000 --- a/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import type { CardRoute, CardRow, PlayQueueAddOptions } from '/@/shared/types/types'; -import type { FixedSizeListProps } from 'react-window'; - -import debounce from 'lodash/debounce'; -import { - forwardRef, - Ref, - useCallback, - useImperativeHandle, - useMemo, - useRef, - useState, -} from 'react'; -import InfiniteLoader from 'react-window-infinite-loader'; - -import { VirtualGridWrapper } from '/@/renderer/components/virtual-grid/virtual-grid-wrapper'; -import { AnyLibraryItem, Genre, LibraryItem } from '/@/shared/types/domain-types'; -import { ListDisplayType } from '/@/shared/types/types'; - -export type VirtualInfiniteGridRef = { - resetLoadMoreItemsCache: () => void; - scrollTo: (index: number) => void; - setItemData: (data: LibraryItemOrGenre[]) => void; - updateItemData: (rule: (item: LibraryItemOrGenre) => LibraryItemOrGenre) => void; -}; - -type LibraryItemOrGenre = AnyLibraryItem | Genre; - -interface VirtualGridProps - extends Omit { - cardRows: CardRow[]; - display?: ListDisplayType; - fetchFn: (options: { columnCount: number; skip: number; take: number }) => Promise; - fetchInitialData?: () => LibraryItemOrGenre[]; - handleFavorite?: (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => void; - handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void; - height?: number; - itemGap: number; - itemSize: number; - itemType: LibraryItem; - loading?: boolean; - minimumBatchSize?: number; - route?: CardRoute; - width?: number; -} - -export const VirtualInfiniteGrid = forwardRef( - ( - { - cardRows, - display, - fetchFn, - fetchInitialData, - handleFavorite, - handlePlayQueueAdd, - height, - initialScrollOffset, - itemCount, - itemGap, - itemSize, - itemType, - loading, - minimumBatchSize, - onScroll, - route, - width, - }: VirtualGridProps, - ref: Ref, - ) => { - const listRef = useRef(null); - const loader = useRef(null); - const minItemCount = useRef(0); - - // itemData can be a sparse array. Treat the intermediate elements as being undefined - const [itemData, setItemData] = useState>( - fetchInitialData?.() || [], - ); - - const { columnCount, itemHeight, rowCount } = useMemo(() => { - const itemsPerRow = width ? Math.floor(width / (itemSize + itemGap * 2)) : 5; - const widthPerItem = Number(width) / itemsPerRow; - const itemHeight = widthPerItem + cardRows.length * 26; - - return { - columnCount: itemsPerRow, - itemHeight, - rowCount: Math.ceil(itemCount / itemsPerRow), - }; - }, [cardRows.length, itemCount, itemGap, itemSize, width]); - - const isItemLoaded = useCallback( - (index: number) => { - const itemIndex = index * columnCount; - - return itemData[itemIndex] !== undefined; - }, - [columnCount, itemData], - ); - - const loadMoreItems = useCallback( - async (startIndex: number, stopIndex: number) => { - if ( - // Fixes a caching bug(?) when switching between filters and the itemCount increases - startIndex === 1 || - // Fixes a caching bug when refreshing items. Prevents a second - // refetch from happening if: - // 1: we are already in a refresh (-1) - // 2: we just had a refresh, and we are index 0 - minItemCount.current === -1 || - (minItemCount.current > 0 && startIndex === 0) - ) - return; - - // Need to multiply by columnCount due to the grid layout - const start = startIndex * columnCount; - const end = stopIndex * columnCount + columnCount; - - const data = await fetchFn({ - columnCount, - skip: start, - take: end - start, - }); - - setItemData((itemData) => { - const newData = [...itemData]; - - let itemIndex = 0; - for (let rowIndex = start; rowIndex < itemCount; rowIndex += 1) { - newData[rowIndex] = data.items[itemIndex]; - itemIndex += 1; - } - - return newData; - }); - }, - [columnCount, fetchFn, itemCount], - ); - - const debouncedLoadMoreItems = debounce(loadMoreItems, 500); - - useImperativeHandle(ref, () => ({ - resetLoadMoreItemsCache: () => { - if (loader.current) { - loader.current.resetloadMoreItemsCache(false); - minItemCount.current = -1; - setItemData([]); - } - }, - scrollTo: (index: number) => { - listRef?.current?.scrollToItem(index); - }, - setItemData: (data: LibraryItemOrGenre[]) => { - setItemData(data); - minItemCount.current = data.length; - }, - updateItemData: (rule) => { - setItemData((data) => data.map((item) => item && rule(item))); - }, - })); - - if (loading) return null; - - return ( - <> - isItemLoaded(index)} - itemCount={itemCount || 0} - loadMoreItems={debouncedLoadMoreItems} - minimumBatchSize={minimumBatchSize} - ref={loader} - threshold={30} - > - {({ onItemsRendered, ref: infiniteLoaderRef }) => ( - { - infiniteLoaderRef(list); - listRef.current = list; - }} - resetInfiniteLoaderCache={() => { - if (loader.current) { - loader.current.resetloadMoreItemsCache(false); - setItemData([]); - } - }} - route={route} - rowCount={rowCount} - width={width} - /> - )} - - - ); - }, -);