Skip to content

Commit 1a5240f

Browse files
committed
Perf: 내 편지함 탄스택 쿼리 적용 (#50)
* fix: 모바일에서 gradient 보이지 않는 문제 해결 * refactor: 내 편지함 및 상세 querykey 적용 - useState을 삭제 하고 데이터 관리 및 성능 최적화를 위해 tanstack query 적용 * fix: 편지 상세 무한 스크롤 오류 수정 - 마지막 편지 보일 시 새로 페이징 하는 로직을 response data에 맞게 수정 - react-intersection-observer 라이브러리를 이용하여 마지막 요소가 view에 들어오는지 확인 * fix: 내 편지함 디자인 보이지 않는 문제 해결 - gradietn class에 !important를 적용 --------- Co-authored-by: nirii00 <[email protected]>
1 parent 38e5f01 commit 1a5240f

File tree

10 files changed

+216
-121
lines changed

10 files changed

+216
-121
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"immer": "^10.1.1",
2323
"react": "^18.3.1",
2424
"react-dom": "^18.3.1",
25+
"react-intersection-observer": "^9.15.1",
2526
"react-router": "^7.1.5",
2627
"swiper": "^11.2.4",
2728
"tailwind-merge": "^3.0.1",

pnpm-lock.yaml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/apis/mailBox.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ export const getMailbox = async () => {
1010
}
1111
};
1212

13-
export const getMailboxDetail = async (id: number) => {
13+
export const getMailboxDetail = async (id: number, pageParam: number) => {
1414
try {
15-
const response = await client.get(`/api/mailbox/${id}`);
15+
const response = await client.get(`/api/mailbox/${id}?page=${pageParam}&size=20`);
16+
// const response = await client.get(`/api/mailbox/${id}`);
17+
1618
if (!response) throw new Error('error while fetching mailbox detail data');
1719
return response.data;
1820
} catch (error) {

src/components/LetterWrapper.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { forwardRef } from 'react';
12
import { twMerge } from 'tailwind-merge';
23

34
interface LetterWrapperProps {
@@ -7,20 +8,23 @@ interface LetterWrapperProps {
78
onClick?: (e: React.MouseEvent<HTMLElement>) => void;
89
}
910

10-
const LetterWrapper = ({ isSender = false, className, children, onClick }: LetterWrapperProps) => {
11-
return (
12-
<article
13-
className={twMerge(
14-
'relative flex overflow-hidden rounded-sm p-4',
15-
isSender ? 'letter-sender-bg' : 'letter-receiver-bg',
16-
className,
17-
)}
18-
onClick={onClick}
19-
>
20-
<div className="z-10 w-full">{children}</div>
21-
<div className="absolute inset-0 z-0 bg-white/50 blur-xl" />
22-
</article>
23-
);
24-
};
11+
const LetterWrapper = forwardRef<HTMLDivElement, LetterWrapperProps>(
12+
({ isSender = false, className, children, onClick }, ref) => {
13+
return (
14+
<article
15+
className={twMerge(
16+
'relative flex overflow-hidden rounded-sm p-4',
17+
isSender ? 'letter-sender-bg' : 'letter-receiver-bg',
18+
className,
19+
)}
20+
onClick={onClick}
21+
ref={ref}
22+
>
23+
<div className="z-10 w-full">{children}</div>
24+
<div className="absolute inset-0 z-0 bg-white/50 blur-xl" />
25+
</article>
26+
);
27+
},
28+
);
2529

2630
export default LetterWrapper;

src/pages/LetterBox/components/LetterBoxItem.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ const LetterBoxItem = ({
3030
className="flex h-fit w-fit flex-col items-center"
3131
onClick={() => handleClickItem(boxId)}
3232
>
33-
<div className="text-gray-70 flex h-25 w-20 flex-col gap-1.5 bg-linear-to-b from-[#D5B695] to-[#B3895D] p-1.5">
33+
<div className="text-gray-70 window-bg flex h-25 w-20 flex-col gap-1.5 bg-linear-to-b p-1.5">
3434
<p
3535
className={twMerge(
3636
'body-m from-white px-1',
3737
isClosed
3838
? 'bg-[repeating-linear-gradient(#D9D9D9,#D9D9D9_17px,#C2C2C2_17px,#C2C2C2_23px)]'
39-
: 'bg-linear-to-b',
40-
isChecked ? 'to-[#FFF5ED]' : 'to-[#FFF4F2]',
39+
: isChecked
40+
? 'window-top-checked'
41+
: 'window-top-unChecked',
4142
)}
4243
>
4344
{zipCode}
@@ -48,7 +49,7 @@ const LetterBoxItem = ({
4849
<div
4950
className={twMerge(
5051
'flex grow flex-col bg-linear-to-b',
51-
isChecked ? 'from-[#FFF7E3] to-[#FFE197]' : 'from-[#FFF4F2] to-[#FFE6E3]',
52+
isChecked ? 'window-bottom-checked' : 'window-bottom-unChecked',
5253
)}
5354
>
5455
<p className="body-r mt-auto mr-[1px] text-right">{letterCount}</p>

src/pages/LetterBox/index.tsx

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useEffect, useState } from 'react';
1+
import { useQuery } from '@tanstack/react-query';
2+
import { useNavigate } from 'react-router';
23

34
import { getMailbox } from '@/apis/mailBox';
45
import DoorImg from '@/assets/images/door.png';
@@ -13,25 +14,34 @@ interface LetterBoxData {
1314
oppositeZipCode: string;
1415
active: boolean;
1516
oppositeRead: boolean;
16-
// totalLetters: number;
17+
letterCount: number;
1718
}
19+
20+
const fetchMailLists = async () => {
21+
const response = await getMailbox();
22+
if (!response) throw new Error();
23+
const data: LetterBoxData[] = response.data;
24+
// 정렬?
25+
return data;
26+
};
27+
1828
const LetterBoxPage = () => {
19-
const [letterBox, setLetterBox] = useState<LetterBoxData[]>([]);
29+
const {
30+
data: letterBox = [],
31+
isLoading,
32+
isError,
33+
} = useQuery({
34+
queryKey: ['mailbox'],
35+
queryFn: fetchMailLists,
36+
staleTime: 1000 * 60 * 5,
37+
gcTime: 1000 * 60 * 10,
38+
});
39+
40+
const navigate = useNavigate();
2041

21-
const fetchMailLists = async () => {
22-
try {
23-
const response = await getMailbox();
24-
if (!response) throw new Error();
25-
const data: LetterBoxData[] = response.data;
26-
// 정렬?
27-
setLetterBox(data);
28-
} catch (error) {
29-
console.error(error);
30-
}
31-
};
32-
useEffect(() => {
33-
fetchMailLists();
34-
}, []);
42+
if (isError) {
43+
navigate('/NotFound');
44+
}
3545

3646
return (
3747
<main className="flex grow flex-col items-center px-5 pt-20">
@@ -42,14 +52,16 @@ const LetterBoxPage = () => {
4252
</p>
4353
<section className="letter-box-bg flex grow flex-col items-center px-4 pt-5">
4454
<div className="flex w-full flex-col gap-5">
45-
{letterBox.length > 0 ? (
55+
{isLoading ? (
56+
<p className="body-m text-gray-60 text-center">로딩중..</p>
57+
) : letterBox.length > 0 ? (
4658
chunkBox(
4759
letterBox.map((data: LetterBoxData, index) => (
4860
<LetterBoxItem
4961
boxId={data.letterMatchingId}
5062
key={index}
5163
zipCode={data.oppositeZipCode}
52-
letterCount={90}
64+
letterCount={data.letterCount}
5365
isChecked={data.oppositeRead}
5466
isClosed={data.active}
5567
/>

src/pages/LetterBoxDetail/components/LetterPreview.tsx

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { forwardRef } from 'react';
12
import { useNavigate } from 'react-router';
23

34
import LetterWrapper from '@/components/LetterWrapper';
5+
import formatDate from '@/utils/formatDate';
46

57
interface LetterPreviewProps {
68
id: number;
@@ -13,18 +15,18 @@ interface LetterPreviewProps {
1315
isClosed: boolean;
1416
zipCode: string;
1517
}
16-
const LetterPreview = ({
17-
id,
18-
date,
19-
title,
20-
isSend,
21-
checked,
22-
isShareMode = false,
23-
onToggle,
24-
isClosed,
25-
zipCode,
26-
}: LetterPreviewProps) => {
27-
// 차단된 편지인경우 편지 보내기 disable
18+
const LetterPreview = forwardRef<HTMLDivElement, LetterPreviewProps>((props, ref) => {
19+
const {
20+
id,
21+
date,
22+
title,
23+
isSend,
24+
checked,
25+
isShareMode = false,
26+
onToggle,
27+
isClosed,
28+
zipCode,
29+
} = props;
2830
const navigate = useNavigate();
2931

3032
const handleItemClick = (id: number) => {
@@ -39,9 +41,9 @@ const LetterPreview = ({
3941

4042
if (isShareMode)
4143
return (
42-
<LetterWrapper isSender={isSend}>
44+
<LetterWrapper isSender={isSend} ref={ref}>
4345
<div className="mb-3 flex items-center justify-between">
44-
<p className="body-r text-gray-80">{date}</p>
46+
<p className="body-r text-gray-80">{formatDate(date)}</p>
4547
<label htmlFor={`${id}`} className="relative">
4648
<input
4749
id={`${id}`}
@@ -58,11 +60,11 @@ const LetterPreview = ({
5860
);
5961

6062
return (
61-
<LetterWrapper isSender={isSend} onClick={() => handleItemClick(id)}>
63+
<LetterWrapper isSender={isSend} onClick={() => handleItemClick(id)} ref={ref}>
6264
<p className="body-r text-gray-80 mb-3">{date}</p>
6365
<p className="body-m text-gray-80 line-clamp-1 break-all">{title}</p>
6466
</LetterWrapper>
6567
);
66-
};
68+
});
6769

6870
export default LetterPreview;

0 commit comments

Comments
 (0)