Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
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;