diff --git a/package.json b/package.json index 3bba84c..b269ddf 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/app/(pages)/4q-gallery/_components/item-container.module.css b/src/app/(pages)/4q-gallery/_components/item-container.module.css index ad78530..1cccaa3 100644 --- a/src/app/(pages)/4q-gallery/_components/item-container.module.css +++ b/src/app/(pages)/4q-gallery/_components/item-container.module.css @@ -17,8 +17,13 @@ } .loadingContainer { - margin-top: 50px; + margin-top: 10px; + padding: 50px; width: 100%; display: flex; justify-content: center; } + +.emptyContainer { + width: 100%; +} \ No newline at end of file diff --git a/src/app/(pages)/4q-gallery/_components/item-container.tsx b/src/app/(pages)/4q-gallery/_components/item-container.tsx index 76e33ea..824f17b 100644 --- a/src/app/(pages)/4q-gallery/_components/item-container.tsx +++ b/src/app/(pages)/4q-gallery/_components/item-container.tsx @@ -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, @@ -48,6 +59,10 @@ export default function Container({ category, tag, sort }: ContainerProps) { gcTime: 300 * 1000, }); + if (inView && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + if (isLoading) { return (
@@ -64,18 +79,22 @@ export default function Container({ category, tag, sort }: ContainerProps) { return (
+ {contextHolder} {items.map((item: Item) => ( ))} {hasNextPage && ( -
- +
+ {isFetchingNextPage ? ( + + ) : ( + + )} +
+ )} + {!hasNextPage && ( +
+
)}
diff --git a/src/types/gallery.ts b/src/types/gallery.ts new file mode 100644 index 0000000..e681106 --- /dev/null +++ b/src/types/gallery.ts @@ -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; +} diff --git a/yarn.lock b/yarn.lock index a193ccc..e8b28e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"