diff --git a/next.config.mjs b/next.config.mjs index 84e4d4b..ddfbb8a 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -4,6 +4,7 @@ const nextConfig = { //로컬 이미지 테스트 하기 위해 localhost를 넣었습니다. domains: ["sprint-fe-project.s3.ap-northeast-2.amazonaws.com", "localhost"], }, + reactStrictMode: false, }; export default nextConfig; diff --git a/src/app/(after-login)/dashboard/[dashboardid]/_components/AddTaskButton.tsx b/src/app/(after-login)/dashboard/[dashboardid]/_components/AddTaskButton.tsx index ff2c1c4..f60e65d 100644 --- a/src/app/(after-login)/dashboard/[dashboardid]/_components/AddTaskButton.tsx +++ b/src/app/(after-login)/dashboard/[dashboardid]/_components/AddTaskButton.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useModalStore } from "@/lib/store/useModalStore"; import Button from "@/components/common/button/Button"; import Image from "next/image"; diff --git a/src/app/(after-login)/dashboard/[dashboardid]/_components/Column.tsx b/src/app/(after-login)/dashboard/[dashboardid]/_components/Column.tsx index c2d445d..2311a51 100644 --- a/src/app/(after-login)/dashboard/[dashboardid]/_components/Column.tsx +++ b/src/app/(after-login)/dashboard/[dashboardid]/_components/Column.tsx @@ -1,3 +1,6 @@ +"use client"; + +import { useEffect, useState, useRef } from "react"; import { DashboardColumn, TaskCardList } from "@/lib/types"; import { fetchTaskCardList } from "@/lib/apis/cardsApi"; import { TOKEN_1 } from "@/lib/constants/tokens"; @@ -5,19 +8,72 @@ import EditColumnButton from "./EditColumnButton"; import AddTaskButton from "./AddTaskButton"; import TaskCard from "./TaskCard"; -export default async function Column({ id, title }: DashboardColumn) { - const { cards, totalCount, cursorId } = await fetchTaskCardList({ - token: TOKEN_1, - id: id, - }); - const items: TaskCardList[] = cards; +const PAGE_SIZE = 3; + +export default function Column({ id, title }: DashboardColumn) { + const [items, setItems] = useState([]); + const [cursorId, setCursorId] = useState(null); + const [totalCount, setTotalCount] = useState(0); + const [isLoading, setIsLoading] = useState(false); + const [isLast, setIsLast] = useState(false); + const observerRef = useRef(null); + + const handleLoad = async () => { + if (isLoading || isLast) return; + setIsLoading(true); + + try { + const { + cards: newCards, + cursorId: nextCursorId, + totalCount, + } = await fetchTaskCardList({ + token: TOKEN_1, + size: PAGE_SIZE, + cursorId, + columnId: id, + }); + + setItems((prev) => [...prev, ...newCards]); + setCursorId(nextCursorId); + setTotalCount(totalCount); + + if (newCards.length < PAGE_SIZE || nextCursorId === null) { + setIsLast(true); + } + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + handleLoad(); + }, []); - // 해당 값 사용하게 되면(페이지네이션) 지울 테스트 코드 - console.log(cursorId); + useEffect(() => { + if (isLast) return; + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting) { + handleLoad(); + } + }, + { threshold: 0.5 } + ); + + const current = observerRef.current; + if (current) observer.observe(current); + + return () => { + if (current) observer.unobserve(current); + observer.disconnect(); + }; + }, [cursorId, isLoading, isLast]); return ( -
-
+
+
@@ -32,11 +88,20 @@ export default async function Column({ id, title }: DashboardColumn) {
-
- - {items.map((item) => ( - - ))} +
+
+ +
+
+ {items.map((item, index) => ( +
+ +
+ ))} +
diff --git a/src/app/(after-login)/dashboard/[dashboardid]/_components/EditColumnButton.tsx b/src/app/(after-login)/dashboard/[dashboardid]/_components/EditColumnButton.tsx index 0c46cd7..1058fbb 100644 --- a/src/app/(after-login)/dashboard/[dashboardid]/_components/EditColumnButton.tsx +++ b/src/app/(after-login)/dashboard/[dashboardid]/_components/EditColumnButton.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useModalStore } from "@/lib/store/useModalStore"; import { useColumnStore } from "@/lib/store/useColumnStore"; import Image from "next/image"; diff --git a/src/lib/apis/cardsApi.ts b/src/lib/apis/cardsApi.ts index e72da65..342ccf9 100644 --- a/src/lib/apis/cardsApi.ts +++ b/src/lib/apis/cardsApi.ts @@ -2,12 +2,21 @@ import { BASE_URL } from "@/lib/constants/urls"; export async function fetchTaskCardList({ token, - id, + size, + cursorId, + columnId, }: { token: string; - id: number; + size: number; + cursorId: number | null; + columnId: number; }) { - const res = await fetch(`${BASE_URL}/cards?size=10&columnId=${id}`, { + let query = `size=${size}&columnId=${columnId}`; + if (cursorId !== null) { + query += `&cursorId=${cursorId}`; + } + + const res = await fetch(`${BASE_URL}/cards?${query}`, { headers: { Accept: "application/json", Authorization: `Bearer ${token}`,