Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 55 lines 1.4 kB view raw
1import type { ReactNode } from "react"; 2import { memo } from "react"; 3import { WindowVirtualizer } from "virtua"; 4import PostsShimmer from "@/components/Shared/Shimmer/PostsShimmer"; 5import { Card, EmptyState, ErrorMessage } from "@/components/Shared/UI"; 6import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect"; 7 8interface PostFeedProps<T extends { id: string }> { 9 items: T[]; 10 loading?: boolean; 11 error?: { message?: string }; 12 hasMore?: boolean; 13 handleEndReached: () => Promise<void>; 14 emptyIcon: ReactNode; 15 emptyMessage: ReactNode; 16 errorTitle: string; 17 renderItem: (item: T) => ReactNode; 18} 19 20const PostFeed = <T extends { id: string }>({ 21 items, 22 loading = false, 23 error, 24 hasMore, 25 handleEndReached, 26 emptyIcon, 27 emptyMessage, 28 errorTitle, 29 renderItem 30}: PostFeedProps<T>) => { 31 const loadMoreRef = useLoadMoreOnIntersect(handleEndReached); 32 33 if (loading) { 34 return <PostsShimmer />; 35 } 36 37 if (!items?.length) { 38 return <EmptyState icon={emptyIcon} message={emptyMessage} />; 39 } 40 41 if (error) { 42 return <ErrorMessage error={error} title={errorTitle} />; 43 } 44 45 return ( 46 <Card className="virtual-divider-list-window"> 47 <WindowVirtualizer> 48 {items.map((item) => renderItem(item))} 49 {hasMore && <span ref={loadMoreRef} />} 50 </WindowVirtualizer> 51 </Card> 52 ); 53}; 54 55export default memo(PostFeed) as typeof PostFeed;