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

Feature: React 쿼리 적용 , MSW 통합 #19

Merged
merged 1 commit into from
Nov 8, 2023
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
2 changes: 1 addition & 1 deletion client/public/mockServiceWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* tslint:disable */

/**
* Mock Service Worker (2.0.3).
* Mock Service Worker (2.0.4).
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
Expand Down
17 changes: 4 additions & 13 deletions client/src/app/@Modal/(.)post/[userId]/[postId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import ModalWrapper from "@/components/ModalWrapper";
import PostDetail from "@/components/post/PostDetail";

const mockData = {
id: "123458",
createdAt: "Mon Nov 06 2023 00:13:07",
nickname: "testNick",
userId: "userID",
userImage: "https://source.unsplash.com/random?wallpapers",
content:
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.",
image: ["https://source.unsplash.com/random?wallpapers"],
tags: ["해시태그1", "해시태그2"],
};
import { Suspense } from "react";

const page = () => {
return (
<ModalWrapper disableBox>
<PostDetail {...mockData} />
<Suspense fallback={<>로딩</>}>
<PostDetail />
</Suspense>
</ModalWrapper>
);
};
Expand Down
7 changes: 4 additions & 3 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Pretendard from "~/assets/font/Pretendard";
import NavigationBar from "~/components/NavigationBar";
import "./globals.css";
import MSWInit from "@/components/mock/MSWInit";
import CustomQueryClientProvider from "@/components/queryClient/CustomQueryClientProvider";

export const metadata: Metadata = {
title: `${nameOfApp} | ${oneLineMessage}`,
Expand All @@ -27,7 +28,7 @@ export default function RootLayout({
return (
<html lang="kr" className={Pretendard.className}>
<body>
<MSWInit>
<CustomQueryClientProvider>
<ThemeRegistry options={{ key: "mui" }}>
{Modal}
<GlobalStyles styles={OverrideCSS} />
Expand All @@ -37,11 +38,11 @@ export default function RootLayout({
overflow: "auto",
}}
>
{children}
<MSWInit>{children}</MSWInit>
</Box>
<NavigationBar />
</ThemeRegistry>
</MSWInit>
</CustomQueryClientProvider>
</body>
</html>
);
Expand Down
11 changes: 10 additions & 1 deletion client/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
"use client";
import PostCardList from "@/components/post/PostCardList";
// import { getPostListQueryFn } from "@/queries/post/useGetPostListQuery";
import { Container } from "@mui/material";
import { Suspense } from "react";

export default function Home() {
// const initialData = await getPostListQueryFn();
return (
<Container sx={{ px: { xs: 0, sm: 4 } }} maxWidth={"lg"}>
<PostCardList />
<Suspense fallback={<>로딩중</>}>
{/* FIXME */}{/* @ts-ignore*/}
<PostCardList
// initialData={initialData}
/>
</Suspense>
</Container>
);
}
8 changes: 3 additions & 5 deletions client/src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
CardMedia,
Typography,
ButtonBase,
Button,
} from "@mui/material";
import PostHashTagList from "./PostHashtagList";
import { useOpenPostDetailPage } from "@/hooks/useOpenPostDetailPage";
Expand All @@ -32,21 +31,20 @@ const PostCard = ({
tagList,
postNo,
likeCount,
profileImgUrls
}: PostInterface) => {
const openPostDetailPage = useOpenPostDetailPage();
// FIXME 유저이미지가 오지 않음
const userImage = undefined;
const hasImage = useMemo(() => postAttachUrl.length !== 0, [postAttachUrl]);

return (
<Card sx={{ display: "flex", gap: 2, p: 2 }}>
<Avatar
sx={{ bgcolor: "secondary.main" }}
sizes="40"
src={userImage}
src={profileImgUrls}
data-testid="avatar"
>
{userImage || id[0].toUpperCase()}
{profileImgUrls || id[0].toUpperCase()}
</Avatar>
<Box>
{/* Header */}
Expand Down
19 changes: 9 additions & 10 deletions client/src/components/post/PostCardList.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
"use client";

import PostCard from "@/components/post/PostCard";
import { PostInterface } from "@/types/post/PostInterface";
import axios from "@/libs/axios";
import { useEffect, useState } from "react";
import useGetPostListQuery from "@/queries/post/useGetPostListQuery";

interface PostCardListProps {
initialData: { content: PostInterface[] };
}

const PostCardList = () => {
const [data, setData] = useState<{ content: PostInterface[] }>();
useEffect(() => {
axios.get<{ content: PostInterface[] }>("/posts").then(({ data }) => {
setData(data);
});
}, []);
const PostCardList = ({ initialData }: PostCardListProps) => {
const { data } = useGetPostListQuery(initialData);

return (
<>
{data?.content.map((post) => (
{data.content.map((post) => (
<PostCard {...post} key={post.postNo} />
))}
</>
Expand Down
46 changes: 27 additions & 19 deletions client/src/components/post/PostDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// FIXME 실제 서버연결시 바꿔야함
"use client";
import { PostInterface } from "@/types/post/PostInterface";
import {
Avatar,
Expand All @@ -11,53 +13,59 @@ import {
Typography,
} from "@mui/material";
import PostHashTagList from "./PostHashtagList";
import { FavoriteBorder, ShareOutlined } from "@mui/icons-material";
import useGetPostDetailQuery from "@/queries/post/useGetPostDetailQuery";

const PostDetail = ({
image,
createdAt,
userId,
nickname,
content,
userImage,
tags,
id,
}: PostInterface) => {
const PostDetail = () => {
const { data } = useGetPostDetailQuery('1');
const {
postAttachUrl,
createdAt,
id,
nickname,
postContent,
tagList,
likeCount,
profileImgUrls,
}: PostInterface = data
return (
<Card sx={{ p: 4 }}>
<CardHeader
avatar={
<Avatar
sx={{ bgcolor: "secondary.main" }}
src={userImage}
src={profileImgUrls}
data-testid="avatar"
>
{userImage || userId[0].toUpperCase()}
{profileImgUrls || id[0].toUpperCase()}
</Avatar>
}
title={`${userId} ${nickname}`}
title={`${id} ${nickname}`}
subheader={createdAt}
sx={{ p: 0 }}
/>
<CardContent sx={{ px: 0 }}>
<Typography variant="body1">{content}</Typography>
<PostHashTagList tags={tags} />
<Typography variant="body1">{postContent}</Typography>
<PostHashTagList tags={tagList} />
</CardContent>
{/* 이미지 */}
{image.length !== 0 && (
{postAttachUrl.length !== 0 && (
<CardMedia
data-testid="postImg"
component="img"
height="360px"
image={image[0]}
alt={`${userId}의 포스트`}
image={postAttachUrl[0]}
alt={`${id}의 포스트`}
sx={{ borderRadius: 2, bgcolor: "background.default" }}
/>
)}
<CardActions sx={{ justifyContent: "end", gap: 2, px: 0 }}>
<ButtonBase data-testid="likeBtn" aria-label="add to favorites">
<Typography>좋아요</Typography>
<FavoriteBorder />
<Typography>{likeCount}</Typography>
</ButtonBase>
<ButtonBase data-testid="shareBtn" aria-label="share">
<ShareOutlined />
<Typography>공유하기</Typography>
</ButtonBase>
</CardActions>
Expand Down
16 changes: 16 additions & 0 deletions client/src/components/queryClient/CustomQueryClientProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactNode, useState } from "react";

export default function CustomQueryClientProvider({
children,
}: {
children?: ReactNode;
}) {
const [queryClient] = useState(() => new QueryClient());

return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
}
38 changes: 3 additions & 35 deletions client/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,6 @@
import { HttpResponse, http } from "msw";
import { randomNumber, randomSelect } from "./utils/random";
import { PostInterface } from "@/types/post/PostInterface";
import getPostList from "./handlers/getPostList";
import getPostDetail from "./handlers/getPostDetail";

export const handlers = [
http.get(`${process.env.NEXT_PUBLIC_BASE_URL}/posts`, () => {
return HttpResponse.json({
content: Array.from(new Array(5)).map((_data, i):PostInterface => {
return {
nickname: "testNick",
id: "userID",
updateDt: "2023-11-08T13:05:09.531Z",
createdAt: "2023-11-08T13:05:09.531Z",
edited: randomSelect<boolean>(true, false),
postNo: i,
postContent:
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.",
positionInfo: "울릉도 동남쪽 뱃길따라 200리",
alcoholName: "string",
postAttachUrl: ["https://source.unsplash.com/random?wallpapers"],
tagList: randomSelect(["tag1", "tag2"], []),
quoteInfo: randomSelect(
[
{
quoteNo: 1,
quoteContent: "1",
},
],
[]
),
likeCount: randomNumber(),
quoteCount: randomNumber(),
followedByMe: randomSelect(true, false),
};
}),
});
}),
getPostList,getPostDetail
];
42 changes: 42 additions & 0 deletions client/src/mocks/handlers/getPostDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { PostInterface } from "@/types/post/PostInterface";
import { HttpResponse, http } from "msw";
import { randomBoolean, randomNumber, randomSelect } from "../utils/random";
/**
* 포스트 상세보기 정보를 받아오는 핸들러
*/
export default http.get(`${process.env.NEXT_PUBLIC_BASE_URL}/posts/1`, () => {
return HttpResponse.json<PostInterface>({
nickname: "testNick",
id: "userID",
updateDt: "2023-11-08T13:05:09.531Z",
createdAt: "2023-11-08T13:05:09.531Z",
edited: randomBoolean(),
postNo: 135,
postContent:
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.",
positionInfo: "울릉도 동남쪽 뱃길따라 200리",
alcoholName: "string",
postAttachUrl: randomSelect(
["https://source.unsplash.com/random?wallpapers"],
[]
),
tagList: randomSelect(["tag1", "tag2"], []),
quoteInfo: randomSelect(
[
{
quoteNo: 1,
quoteContent: "1",
},
],
[]
),
likeCount: randomNumber(),
quoteCount: randomNumber(),
followedByMe: randomBoolean(),
likedByme: randomBoolean(),
profileImgUrls: randomSelect(
"https://source.unsplash.com/random?wallpapers",
""
),
});
});
47 changes: 47 additions & 0 deletions client/src/mocks/handlers/getPostList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { PostInterface } from "@/types/post/PostInterface";
import { HttpResponse, http } from "msw";
import { randomBoolean, randomNumber, randomSelect } from "../utils/random";
/**
* 포스트 리스트를 받아오는 핸들러
*/
export default http.get(`${process.env.NEXT_PUBLIC_BASE_URL}/posts`, () => {
return HttpResponse.json({
content: Array.from(new Array(5)).map((_data, i): PostInterface => {
return {
nickname: "testNick",
id: "userID",
updateDt: "2023-11-08T13:05:09.531Z",
createdAt: "2023-11-08T13:05:09.531Z",
edited: randomBoolean(),
postNo: i,
postContent:
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.",
positionInfo: "울릉도 동남쪽 뱃길따라 200리",
alcoholName: "string",
postAttachUrl: randomSelect(
["https://source.unsplash.com/random?wallpapers"],
[]
),
tagList: randomSelect(["tag1", "tag2"], []),
quoteInfo: randomSelect(
[
{
quoteNo: 1,
quoteContent: "1",
},
],
[]
),
likeCount: randomNumber(),
quoteCount: randomNumber(),
followedByMe: randomBoolean(),
likedByme: randomBoolean(),
profileImgUrls: randomSelect(
"https://source.unsplash.com/random?wallpapers",
""
),
};
}),
});
});

Loading
Loading