Replies: 2 comments 9 replies
-
@davbrito did you have any luck with this? Also in the same situation! |
Beta Was this translation helpful? Give feedback.
9 replies
-
Hi there guys, just posting this as an example for virtualizing a list using @tanstack/react-virtual + Shadcn ScrollArea: ScrollArea: import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
import * as React from 'react';
import { cn } from '@/lib/utils';
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> & {
viewPortClassName?: string;
orientation?: 'vertical' | 'horizontal';
viewPortRef?: React.RefObject<HTMLDivElement>;
}
>(
(
{
className,
children,
viewPortClassName,
viewPortRef,
orientation = 'vertical',
...props
},
ref,
) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn('relative overflow-hidden', className)}
{...props}
>
<ScrollAreaPrimitive.Viewport
className={cn(
'size-full rounded-[inherit] [&>div]:!block',
viewPortClassName,
)}
ref={viewPortRef}
>
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar orientation={orientation} />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
),
); Virtualized List Component: import { useVirtualizer } from '@tanstack/react-virtual';
import * as React from 'react';
import { isNil } from '@activepieces/shared';
import { ScrollArea } from './scroll-area';
interface VirtualizedScrollAreaProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
overscan?: number;
estimateSize: (index: number) => number;
getItemKey?: (index: number) => string | number;
listHeight: number;
className?: string;
initialScroll?: {
index: number;
clickAfterScroll: boolean;
};
}
export interface VirtualizedScrollAreaRef {
scrollToIndex: (
index: number,
options?: {
align?: 'start' | 'center' | 'end';
behavior?: 'auto' | 'smooth';
},
) => void;
}
const VirtualizedScrollArea = ({
items,
renderItem,
overscan = 5,
estimateSize,
getItemKey,
listHeight,
initialScroll,
className,
...props
}: VirtualizedScrollAreaProps<any>) => {
const parentRef = React.useRef<HTMLDivElement>(null);
const rowVirtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: estimateSize,
overscan,
getItemKey: getItemKey || ((index) => index),
});
const virtualItems = rowVirtualizer.getVirtualItems();
React.useEffect(() => {
if (isNil(initialScroll)) {
return;
}
if (initialScroll?.index > -1) {
rowVirtualizer.scrollToIndex(initialScroll.index, {
align: 'start',
behavior: 'auto',
});
if (initialScroll?.clickAfterScroll) {
//need to wait for the scroll to be completed
setTimeout(() => {
const targetElement = parentRef.current?.querySelector(
`[data-virtual-index="${initialScroll.index}"]`,
);
const renderedElement = targetElement?.children[0];
if (renderedElement instanceof HTMLElement) {
renderedElement.click();
}
}, 100);
}
}
}, [initialScroll?.index, rowVirtualizer]);
return (
<ScrollArea
style={{ height: `${listHeight}px` }}
viewPortRef={parentRef}
{...props}
>
<div
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
width: '100%',
position: 'relative',
}}
>
{virtualItems.map((virtualItem) => (
<div
key={virtualItem.key}
data-virtual-index={virtualItem.index}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
{renderItem(items[virtualItem.index], virtualItem.index)}
</div>
))}
</div>
</ScrollArea>
);
};
VirtualizedScrollArea.displayName = 'VirtualizedScrollArea';
export { VirtualizedScrollArea }; |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
There are several good packages for making virtualized lists. We have react-virtual, react-virtualized, react-virtuoso, react-window, etc.
What would be the "official" or recommended approach for doing that kind of list with the
ScrollArea
primitive, and what library is best suited for the job?I've tried to do it in the past with no success. If you have had some experience doing it, please share your approach.
Beta Was this translation helpful? Give feedback.
All reactions