Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR] useSuspenseQuery 및 Suspense 적용 #205

Merged
merged 5 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/app/mypage/_components/Fallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Spinner } from '@/components/common/spinner';

const Fallback = () => {
return (
<div className="flex size-full flex-col items-center justify-center">
<Spinner />
</div>
);
};

export default Fallback;
16 changes: 8 additions & 8 deletions src/app/mypage/_components/MyTest.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
'use client';

import { Suspense } from 'react';

import { ResultCard, ResultCardContainer } from '@/components/features/test/resultCard';
import { EmptyTest } from '@/components/shared';
import { useGetMyTest } from '@/hooks/test';

import { Fallback as MyTestFallback } from '.';

const MyTest = () => {
const { data, status } = useGetMyTest();
const { data } = useGetMyTest();

return (
<>
<Suspense fallback={<MyTestFallback />}>
<ResultCardContainer>
{status === 'pending' ? (
<></>
) : status === 'error' ? (
<></>
) : data.length > 0 ? (
{data.length > 0 ? (
data.map((result) => <ResultCard key={result.id} result={result} />)
) : (
<EmptyTest />
)}
</ResultCardContainer>
</>
</Suspense>
);
};

Expand Down
17 changes: 7 additions & 10 deletions src/app/mypage/_components/MyVote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dayjs from 'dayjs';
import Link from 'next/link';
import { useRef } from 'react';
import { Suspense, useRef } from 'react';

import { Button } from '@/components/common/button';
import { Icon } from '@/components/common/icon';
Expand All @@ -14,22 +14,19 @@ import { useDeleteVoteMutation, useGetMyVote } from '@/hooks/vote';
import { VoteType } from '@/types/vote';
import { fromNowOf } from '@/utils/dates';

import { Fallback as MyVoteFallback } from '.';

type BottomSheetType = 'askDelete' | 'selectOption';

const MyVote = () => {
const { data, status } = useGetMyVote();
const { data } = useGetMyVote();
const { mutate: onDelete, isPending } = useDeleteVoteMutation();
const { onOpenSheet, openedSheet, onCloseSheet } = useBottomSheetState<BottomSheetType>();
const deleteTarget = useRef<VoteType['id'] | null>(null);

// TODO Suspense or ssr
return (
<>
{status === 'pending' ? (
<></>
) : status === 'error' ? (
<></>
) : data.length > 0 ? (
<Suspense fallback={<MyVoteFallback />}>
{data.length > 0 ? (
<div className="mt-3xs flex flex-col gap-3xs">
{data.map((vote) => (
<VoteCard key={vote.id}>
Expand Down Expand Up @@ -114,7 +111,7 @@ const MyVote = () => {
) : (
<EmptyVote />
)}
</>
</Suspense>
);
};

Expand Down
1 change: 1 addition & 0 deletions src/app/mypage/_components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as Fallback } from './Fallback';
export { default as MyTest } from './MyTest';
export { default as MyVote } from './MyVote';
export { default as Profile } from './Profile';
65 changes: 34 additions & 31 deletions src/app/vote/[slug]/_component/Replies.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useCallback, useRef, useState } from 'react';
import { Suspense, useCallback, useRef, useState } from 'react';

import { ControlTab } from '@/components/common/controlTab';
import { Spinner } from '@/components/common/spinner';
Expand All @@ -23,7 +23,7 @@ type Props = {

const Replies = ({ voteId }: Props) => {
const { data: user } = useGetUser();
const { status, data: replies } = useGetVoteReplies({ voteId });
const { data: replies } = useGetVoteReplies({ voteId });
const { mutateAsync: createVoteReplyAsync } = useCreateVoteReplyMutation();
const { mutate: deleteVoteReply } = useDeleteVoteReplyMutation();
const { mutate: toggleLikeVoteReply } = useLikeVoteReplyMutation();
Expand Down Expand Up @@ -55,35 +55,30 @@ const Replies = ({ voteId }: Props) => {

<Notice text="댓글을 사용할 때는 타인을 존중해야합니다." />

{/* TODO: Suspense or SSR */}
{status === 'pending' ? (
<div className="flex h-full items-center justify-center py-lg">
<Spinner />
</div>
) : status === 'error' ? (
<div>에러</div>
) : sortedReplyData.length > 0 ? (
<ul className="flex h-full flex-col px-2xs py-3xs">
{sortedReplyData.map((reply) => (
<Reply
key={reply.commentId}
reply={reply}
onLikeToggle={() =>
toggleLikeVoteReply({ voteId: reply.voteId, commentId: reply.commentId })
}
onDelete={() =>
deleteVoteReply({
commentId: reply.commentId,
voteId: reply.voteId,
})
}
isWrittenByCurrentUser={reply.userId === user?.userId}
/>
))}
</ul>
) : (
<NoReplies />
)}
<Suspense fallback={<ReplyFallback />}>
{sortedReplyData.length > 0 ? (
<ul className="flex h-full flex-col px-2xs py-3xs">
{sortedReplyData.map((reply) => (
<Reply
key={reply.commentId}
reply={reply}
onLikeToggle={() =>
toggleLikeVoteReply({ voteId: reply.voteId, commentId: reply.commentId })
}
onDelete={() =>
deleteVoteReply({
commentId: reply.commentId,
voteId: reply.voteId,
})
}
isWrittenByCurrentUser={reply.userId === user?.userId}
/>
))}
</ul>
) : (
<NoReplies />
)}
</Suspense>

<ReplyInput
onSubmit={async (content) => {
Expand All @@ -95,6 +90,14 @@ const Replies = ({ voteId }: Props) => {
);
};

const ReplyFallback = () => {
return (
<div className="flex h-full items-center justify-center py-lg">
<Spinner />
</div>
);
};

const NoReplies = () => {
return (
<div className="flex h-full items-center justify-center py-lg">
Expand Down
92 changes: 46 additions & 46 deletions src/app/vote/[slug]/_component/VoteDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { notFound } from 'next/navigation';
import { Suspense } from 'react';

import { Button } from '@/components/common/button';
import { Icon } from '@/components/common/icon';
Expand All @@ -17,61 +17,61 @@ type Props = {
};

const VoteDetail = ({ voteId }: Props) => {
const { status, data } = useGetVoteById(voteId);
const { data } = useGetVoteById(voteId);
const { mutate: toggleLike } = useLikeVoteMutation();

return (
<section className="h-fit px-2xs">
{status === 'pending' ? (
<div className="flex min-h-[480px] items-center justify-center">
<Spinner />
</div>
) : status === 'error' ? (
notFound()
) : (
<>
<VoteExtraDetail
voteId={data.id}
author={data.user}
views={data.views}
category={data.category}
/>
<Suspense fallback={<VoteDetailFallback />}>
<VoteExtraDetail
voteId={data.id}
author={data.user}
views={data.views}
category={data.category}
/>

<Typography type="title2" className="mt-3xs text-gray-1000">
Q. {data.title}
</Typography>
<Typography type="body3" className="mb-3xs mt-4xs text-gray-500">
{data.content}
</Typography>
<Typography type="title2" className="mt-3xs text-gray-1000">
Q. {data.title}
</Typography>
<Typography type="body3" className="mb-3xs mt-4xs text-gray-500">
{data.content}
</Typography>

<VoteCard>
<VoteCard.Header
closeDate={data.closeDate}
voter={data.voters}
fontColor="text-gray-600"
fontSize="text-xs"
/>
<VoteCard>
<VoteCard.Header
closeDate={data.closeDate}
voter={data.voters}
fontColor="text-gray-600"
fontSize="text-xs"
/>

<Voting voteId={data.id} selected={data.selected} selections={data.selections} />
</VoteCard>
<Voting voteId={data.id} selected={data.selected} selections={data.selections} />
</VoteCard>

<div className="mb-3xs mt-sm flex justify-between">
<LikeButton
isLiked={data.isLiked}
likeCount={data.likes}
onClick={() => toggleLike({ voteId })}
/>
<Button
iconOnly
Icon={<Icon icon="share" color="gray-300" />}
variant="empty"
className="!p-0"
/>
</div>
</>
)}
<div className="mb-3xs mt-sm flex justify-between">
<LikeButton
isLiked={data.isLiked}
likeCount={data.likes}
onClick={() => toggleLike({ voteId })}
/>
<Button
iconOnly
Icon={<Icon icon="share" color="gray-300" />}
variant="empty"
className="!p-0"
/>
</div>
</Suspense>
</section>
);
};

const VoteDetailFallback = () => {
return (
<div className="flex min-h-[480px] items-center justify-center">
<Spinner />
</div>
);
};

export default VoteDetail;
8 changes: 4 additions & 4 deletions src/app/vote/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ type Props = {
params: { slug: string };
};

const VoteDetailPage = async ({ params }: Props) => {
const voteId = params.slug;
const VoteDetailPage = ({ params }: Props) => {
const voteId = +params.slug;

return (
<>
<VoteDetail voteId={Number(voteId)} />
<VoteDetail voteId={voteId} />
<Divider height={8} />
<Replies voteId={Number(voteId)} />
<Replies voteId={voteId} />
</>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/test/useGetMyTest.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';

import { donworryApi } from '@/api';
import { queryKey } from '@/api/queryKey';

const useGetMyTest = () => {
return useQuery({
return useSuspenseQuery({
queryKey: queryKey.test.myResult,
queryFn: donworryApi.test.getMyTest,
});
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/vote/useGetMyVote.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';

import { donworryApi } from '@/api';
import { queryKey } from '@/api/queryKey';

const useGetMyVote = () => {
return useQuery({
return useSuspenseQuery({
queryFn: donworryApi.vote.getMyVotes,
queryKey: queryKey.vote.myVotes(),
retry: 1,
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/vote/useGetVoteById.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';

import { donworryApi } from '@/api';
import { queryKey } from '@/api/queryKey';

export const useGetVoteById = (voteId: number) => {
return useQuery({
return useSuspenseQuery({
queryKey: queryKey.vote.detail(voteId),
queryFn: () => donworryApi.vote.getVoteById({ voteId }),
});
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/vote/useGetVoteReplies.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';

import { donworryApi } from '@/api';
import { queryKey } from '@/api/queryKey';
import { GetVoteRepliesRequest } from '@/api/vote/types';

const useGetVoteReplies = ({ voteId }: GetVoteRepliesRequest) => {
return useQuery({
return useSuspenseQuery({
queryKey: queryKey.vote.reply(voteId),
queryFn: () => donworryApi.vote.getVoteReplies({ voteId }),
});
Expand Down
Loading