-
Notifications
You must be signed in to change notification settings - Fork 60
Open
Description
Hey @jaredLunde
There's a bunch of things I'm trying to do together:
Now if I add allMedia to usePositioner deps, because of the Infinite scroll, the grid starts glitching,
I also wanted to have loaders at the end as shown in the itemsWithPlaceholders, now if i switch the tabs and the data changes it errors out and if i put allMedia in the deps, it keeps glitching
Also one issue related to the grid rendering, whenever i render it for the first time the height and width are 0 and then if I change the filter it renders!
Would appreciate a lot if you can help me out with this thanks!
For reference this is my code:
import {
useInfiniteLoader,
useMasonry,
usePositioner,
useResizeObserver,
} from 'masonic';
import { SkeletonTile } from './components/Skeleton';
import { useScroller, useSize } from 'mini-virtual-list';
export const LOADER_ID_PREFIX = '__skeleton__';
export const GUTTER_SIZE = 3;
type GridProps<T> = {
allMedia: T[];
renderItem: (mediaItem: T) => React.ReactNode;
maxColumnCount?: number;
loaderGridSize?: number;
isLoading?: boolean;
isFetchingMore?: boolean;
hasMore?: boolean;
resetGrid?: boolean;
onLoadMore?: () => Promise<any>;
// Pass in a ref function to get the scroll container element
scrollContainer: MutableRefObject<HTMLElement | null>;
};
const Grid = <T,>({
allMedia = [],
renderItem,
maxColumnCount = 5,
loaderGridSize = 9,
isLoading = false,
isFetchingMore = false,
hasMore = false,
onLoadMore,
scrollContainer,
}: GridProps<T>) => {
const { scrollTop, isScrolling } = useScroller(scrollContainer);
const { width, height } = useSize(scrollContainer);
const positioner = usePositioner(
{
width,
columnGutter: GUTTER_SIZE,
rowGutter: GUTTER_SIZE,
maxColumnCount,
},
[],
);
const resizeObserver = useResizeObserver(positioner);
const itemsWithPlaceholders = useMemo(() => {
if (!isFetchingMore && !isLoading) return allMedia;
return [...allMedia, ...getPlaceHolderItems<T>(loaderGridSize)];
}, [allMedia, isFetchingMore, isLoading, loaderGridSize]);
const loadMoreItems = useCallback(async () => {
if (!hasMore || !onLoadMore || isFetchingMore) return;
await onLoadMore();
}, [hasMore, onLoadMore, isFetchingMore]);
const isItemLoaded = useCallback(
(idx: number) => idx < allMedia.length,
[allMedia.length],
);
const maybeLoadMore = useInfiniteLoader(loadMoreItems, {
isItemLoaded,
threshold: Math.max(6, loaderGridSize),
});
const itemKey = useCallback((data: any, index: number) => {
return data?.id ?? `item-${index}`;
}, []);
const renderItems = useCallback(
({ data }: { data: T }) => {
if ((data as any)?.id?.startsWith(LOADER_ID_PREFIX)) {
return <SkeletonTile />;
}
return renderItem(data);
},
[renderItem],
);
return useMasonry({
id: 'dream-masonry-grid',
positioner,
resizeObserver,
items: itemsWithPlaceholders,
height,
scrollTop,
isScrolling,
overscanBy: 2,
itemKey,
itemHeightEstimate: 300,
render: renderItems,
onRender: maybeLoadMore,
});
};
export default DreamGrid;
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels