From 8b953d1e75dee4b7d78546403d11c97463d2ddc8 Mon Sep 17 00:00:00 2001 From: jmj Date: Thu, 4 Jul 2024 20:57:39 +0900 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20refactor(#167):=20?= =?UTF-8?q?=EB=82=B4=20=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=EC=82=AC=EC=9D=B4=EB=93=9C=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mydashboard/DashboardList/index.tsx | 54 +++++++------- .../InvitedDashboardList/index.tsx | 72 ++++++++++--------- src/hooks/useSignIn.ts | 2 +- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/containers/mydashboard/DashboardList/index.tsx b/src/containers/mydashboard/DashboardList/index.tsx index dfa462fd..5a5aadcb 100644 --- a/src/containers/mydashboard/DashboardList/index.tsx +++ b/src/containers/mydashboard/DashboardList/index.tsx @@ -16,8 +16,9 @@ export default function DashboardList({ initialDashboard }: DashboardListProps) const [currentChunk, setCurrentChunk] = useState(1); const { openNewDashboardModal } = useModal(); const [dashboardData, setDashboards] = useState(initialDashboard); - const [isInitial, setIsInitial] = useState(true); + const [isInitial, setIsInitial] = useState(!!initialDashboard); + // 대시보드 데이터를 가져오는 커스텀 훅 사용 const { data: dashboardResponse, error, @@ -26,7 +27,19 @@ export default function DashboardList({ initialDashboard }: DashboardListProps) getDashboardsList('pagination', currentChunk, 5), ); - const totalPage = initialDashboard.totalCount ? Math.max(1, Math.ceil(initialDashboard.totalCount / 5)) : 1; + // 총 페이지 수 계산 + const totalPage = initialDashboard?.totalCount ? Math.max(1, Math.ceil(initialDashboard.totalCount / 5)) : 1; + + // 대시보드 데이터가 변경될 때 상태 업데이트 + useEffect(() => { + if (dashboardResponse) { + if (!isInitial) { + setDashboards(dashboardResponse); + } else { + setIsInitial(false); + } + } + }, [dashboardResponse, isInitial]); if (error) { return ( @@ -37,53 +50,44 @@ export default function DashboardList({ initialDashboard }: DashboardListProps) ); } + // 다음 페이지로 이동하는 함수 const handleNext = () => { if (currentChunk < totalPage) { setCurrentChunk((prev) => prev + 1); } }; + + // 이전 페이지로 이동하는 함수 const handlePrev = () => { if (currentChunk > 1) { setCurrentChunk((prev) => prev - 1); } }; - useEffect(() => { - if (dashboardResponse) { - if (!isInitial) { - setDashboards(dashboardResponse); - } else { - setIsInitial(false); - } - } - }, [dashboardResponse]); - - if (!dashboardData) return; + if (!dashboardData) return null; return (
    + {/* 새로운 대시보드 생성 버튼 */}
  • - {isLoading && !isInitial ? ( - <> - {[...Array(5)].map((_, i) => ( + {/* 대시보드 목록 표시 */} + {isLoading && !isInitial + ? [...Array(5)].map((_, i) => (
  • - ))} - - ) : ( - <> - {dashboardData.dashboards.map((dashboard) => ( + )) + : dashboardData.dashboards.map((dashboard) => (
  • - +
    -

    {dashboard.title}

    +

    {dashboard.title}

    {dashboard.createdByMe && ( my @@ -93,9 +97,7 @@ export default function DashboardList({ initialDashboard }: DashboardListProps)
  • ))} - - )} - + {/* 페이지네이션 */}
    (initialInvitedDashboard.invitations); - const [isInitial, setIsInitial] = useState(true); +const InvitedDashboardList = ({ initialInvitedDashboard }: InvitedDashboardListProps) => { + const [invitations, setInvitations] = useState(initialInvitedDashboard?.invitations || []); + const [isInitial, setIsInitial] = useState(!initialInvitedDashboard); const [isFetchingNextPage, setIsFetchingNextPage] = useState(false); const [isSearching, setIsSearching] = useState(false); const observerRef = useRef(null); @@ -26,59 +26,57 @@ export default function InvitedDashboardList({ initialInvitedDashboard }: Invite const queryClient = useQueryClient(); - const { data, error, isLoading } = useFetchData(['invitations'], () => getInvitationsList()); + // 데이터를 가져오는 커스텀 훅 + const { data, error, isLoading } = useFetchData(['invitations'], getInvitationsList); + // 데이터가 변경될 때 초대 상태 업데이트 useEffect(() => { if (data) { if (!isInitial) { setInvitations(data.invitations); - setCursorId(data.cursorId ? data.cursorId : 0); + setCursorId(data.cursorId ?? 0); } else { setIsInitial(false); } } - }, [data]); + }, [data, isInitial]); - const handleMoreInvitations = async (currentCursorId: number) => { + // 더 많은 초대 데이터를 가져오는 함수 + const handleMoreInvitations = useCallback(async (currentCursorId: number) => { if (currentCursorId !== 0) { + setIsFetchingNextPage(true); try { - setIsFetchingNextPage(true); const { data: nextData } = await getInvitationsList(10, currentCursorId); - if (nextData.invitations.length > 0) { setInvitations((prevInvitations) => [...prevInvitations, ...nextData.invitations]); } - setCursorId(nextData.cursorId || 0); + setCursorId(nextData.cursorId ?? 0); } catch (err) { console.error('데이터를 가져오는 중 오류가 발생했습니다:', err); } finally { setIsFetchingNextPage(false); } } - }; + }, []); + // IntersectionObserver 콜백 함수 const handleObserver = useCallback( - async (entries: IntersectionObserverEntry[]) => { + (entries: IntersectionObserverEntry[]) => { const target = entries[0]; - if (target.isIntersecting && !isFetchingNextPage && cursorId && !isSearching) { handleMoreInvitations(cursorId); } }, - [cursorId, isFetchingNextPage, isSearching], + [cursorId, isFetchingNextPage, isSearching, handleMoreInvitations], ); + // IntersectionObserver 설정 useEffect(() => { - const observer = new IntersectionObserver(handleObserver, { - threshold: 0.8, - }); - + const observer = new IntersectionObserver(handleObserver, { threshold: 0.8 }); const currentObserverRef = observerRef.current; - if (currentObserverRef) { observer.observe(currentObserverRef); } - return () => { if (currentObserverRef) { observer.unobserve(currentObserverRef); @@ -86,6 +84,7 @@ export default function InvitedDashboardList({ initialInvitedDashboard }: Invite }; }, [observerRef, handleObserver]); + // 초대 수락/거절 처리 함수 const handleAcceptInvitation = async (invitationId: number, inviteAccepted: boolean) => { try { await putAcceptInvitation(invitationId, inviteAccepted); @@ -97,17 +96,20 @@ export default function InvitedDashboardList({ initialInvitedDashboard }: Invite } }; - const handleChangeSearch = debounce(async (e: React.ChangeEvent) => { - const searchValue = e.target.value; - setIsSearching(!!searchValue); - - try { - const { data: searchData } = await getInvitationsList(10, 0, searchValue); - setInvitations(searchData.invitations); - } catch (err) { - console.error('데이터를 가져오는 중 오류가 발생했습니다:', err); - } - }, 300); + // 검색어 변경 처리 함수 + const handleChangeSearch = useCallback( + debounce(async (e: React.ChangeEvent) => { + const searchValue = e.target.value; + setIsSearching(!!searchValue); + try { + const { data: searchData } = await getInvitationsList(10, 0, searchValue); + setInvitations(searchData.invitations); + } catch (err) { + console.error('데이터를 가져오는 중 오류가 발생했습니다:', err); + } + }, 300), + [], + ); if (error) { return ( @@ -121,10 +123,12 @@ export default function InvitedDashboardList({ initialInvitedDashboard }: Invite ); } + if (!invitations) return null; + return (

    초대받은 대시보드

    - {isLoading && !isInitial ? ( + {isLoading && !isInitial && !initialInvitedDashboard ? ( ) : ( <> @@ -149,4 +153,6 @@ export default function InvitedDashboardList({ initialInvitedDashboard }: Invite )}
    ); -} +}; + +export default InvitedDashboardList; diff --git a/src/hooks/useSignIn.ts b/src/hooks/useSignIn.ts index ce51836d..6d5f787e 100644 --- a/src/hooks/useSignIn.ts +++ b/src/hooks/useSignIn.ts @@ -23,7 +23,7 @@ export const useSignIn = () => { onSuccess: (data) => { dispatch(setUser(data)); dispatch(isLoading(false)); - setCookie('token', data.accessToken, { httpOnly: true, sameSite: 'strict' }); + setCookie('token', data.accessToken); }, onMutate: async () => { dispatch(isLoading(true));