Skip to content

Commit

Permalink
feature: apply intersection observer for infinite scroll in gallery
Browse files Browse the repository at this point in the history
  • Loading branch information
moolmin committed Nov 23, 2024
1 parent 7200ad8 commit 1d94c8c
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 25 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"react-dom": "^18.3.1",
"react-horizontal-scrolling-menu": "^7.1.4",
"react-icons": "^5.2.1",
"react-intersection-observer": "^9.13.1",
"react-konva": "^18.2.10",
"react-konva-utils": "^1.0.6",
"react-lottie-player": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
}

.loadingContainer {
margin-top: 50px;
margin-top: 10px;
padding: 50px;
width: 100%;
display: flex;
justify-content: center;
}

.emptyContainer {
width: 100%;
}
67 changes: 43 additions & 24 deletions src/app/(pages)/4q-gallery/_components/item-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@ import { useInfiniteQuery } from "@tanstack/react-query";
import styles from "./item-container.module.css";
import ItemCard from "./item-card";
import { getGalleryData } from "@/service/photo_api";
import { Button } from "antd";
import { BounceDot } from "basic-loading";
import { Item } from "@/types/item";
import { GalleryPage, ContainerProps } from "@/types/gallery";
import { useInView } from "react-intersection-observer";
import { message } from "antd";

type GalleryPage = {
content: Item[];
page: number;
number: number;
last: boolean;
totalPages: number;
totalElements: number;
};
export default function Container({ category, tag, sort }: ContainerProps) {
const [messageApi, contextHolder] = message.useMessage();

type ContainerProps = {
category: string;
tag: string;
sort: string;
};
const warning = () => {
messageApi.open({
type: "warning",
content: "더 이상 불러올 데이터가 없습니다.",
duration: 1.2,
style: {
marginTop: "40px",
},
});
};

const { ref, inView } = useInView({
threshold: 0.2,
triggerOnce: false,
onChange: (inView) => {
if (inView && !hasNextPage) {
warning();
}
},
});

export default function Container({ category, tag, sort }: ContainerProps) {
const loadingOption = {
size: 12,
size: 10,
color: "#FE5B10",
};

const {
data,
isLoading,
Expand All @@ -48,6 +59,10 @@ export default function Container({ category, tag, sort }: ContainerProps) {
gcTime: 300 * 1000,
});

if (inView && hasNextPage && !isFetchingNextPage) {
fetchNextPage();
}

if (isLoading) {
return (
<div className={styles.loadingContainer}>
Expand All @@ -64,18 +79,22 @@ export default function Container({ category, tag, sort }: ContainerProps) {

return (
<div className={styles.container}>
{contextHolder}
{items.map((item: Item) => (
<ItemCard key={item.imageId} item={item} />
))}
{hasNextPage && (
<div className={styles.moreBtnContainer}>
<Button
onClick={() => fetchNextPage()}
loading={isFetchingNextPage}
className={styles.moreBtn}
>
더보기
</Button>
<div ref={ref} className={styles.loadingContainer}>
{isFetchingNextPage ? (
<BounceDot option={loadingOption} />
) : (
<span> </span>
)}
</div>
)}
{!hasNextPage && (
<div className={styles.emptyContainer} ref={ref}>

</div>
)}
</div>
Expand Down
16 changes: 16 additions & 0 deletions src/types/gallery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Item } from "@/types/item";

export interface GalleryPage {
content: Item[];
page: number;
number: number;
last: boolean;
totalPages: number;
totalElements: number;
}

export interface ContainerProps {
category: string;
tag: string;
sort: string;
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4802,6 +4802,11 @@ react-icons@^5.2.1:
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.3.0.tgz#ccad07a30aebd40a89f8cfa7d82e466019203f1c"
integrity sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==

react-intersection-observer@^9.13.1:
version "9.13.1"
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.13.1.tgz#6c61a75801162491c6348bad09967f2caf445584"
integrity sha512-tSzDaTy0qwNPLJHg8XZhlyHTgGW6drFKTtvjdL+p6um12rcnp8Z5XstE+QNBJ7c64n5o0Lj4ilUleA41bmDoMw==

react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand Down

0 comments on commit 1d94c8c

Please sign in to comment.