Skip to content

Commit

Permalink
인기게시글-불러오기-기능-추가 (#93)
Browse files Browse the repository at this point in the history
* New : 인기 게시글을 불러오는 Server path 추가

* New : 인기게시글을 불러오는 쿼리 추가

* New : 인기 게시글 불러오기 기능 추가
  • Loading branch information
jobkaeHenry authored Jan 5, 2024
1 parent 0c567b1 commit 11f70db
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 4 deletions.
9 changes: 6 additions & 3 deletions client/src/components/post/MainPagePostList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import PostCardList from "@/components/post/PostCardList";
import CustomContainer from "@/components/layout/CustomContainer";
import { useState } from "react";
import CustomToggleButtonGroup from "@/components/CustomToggleButtonGroup";
import PopularPostCardList from "./PopularPostCardList";

type Props = {
initialData: AugmentedGetPostListResponse;
Expand All @@ -19,11 +20,13 @@ const MainPagePostList = ({ initialData }: Props) => {
<CustomToggleButtonGroup
value={selectableList}
onChange={setCurrentView}
sx={{ position: "fixed", top: 0, left: 0, right: 0,zIndex:1 }}
sx={{ position: "fixed", top: 0, left: 0, right: 0, zIndex: 1 }}
/>
<CustomContainer mt={5}>
{currentView==="전체 캐스크"&&<PostCardList initialData={initialData} />}
{currentView==="인기"&&<PostCardList sort="likeCount"/>}
{currentView === "전체 캐스크" && (
<PostCardList initialData={initialData} />
)}
{currentView === "인기" && <PopularPostCardList />}
</CustomContainer>
</>
);
Expand Down
64 changes: 64 additions & 0 deletions client/src/components/post/PopularPostCardList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"use client";

import PostCard from "@/components/post/PostCard";
import useGetPopularPostListInfiniteQuery, {
UseGetPopularPostListQueryInterface,
} from "@/queries/post/useGetPopularPostListInfiniteQuery";
import { useInView } from "react-intersection-observer";
import { useEffect } from "react";
import { Stack } from "@mui/material";
import { useMemo } from "react";
import Image from "next/image";
import NoResult from "@/assets/images/noResult.png";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import PostCardSkeleton from "./PostCardSkeleton";

function PopularPostCardList(props: UseGetPopularPostListQueryInterface) {
const {
data,
fetchNextPage,
isFetchingNextPage,
hasNextPage,
isSuccess,
isLoading,
} = useGetPopularPostListInfiniteQuery({
...props,
headers: { Authorization: getTokenFromLocalStorage() },
});

const { ref, inView } = useInView();
useEffect(() => {
if (hasNextPage && inView) fetchNextPage();
}, [inView, hasNextPage]);

const hasResult = useMemo(
() => data && data.pages[0].content.length > 0,
[data]
);

return (
<div>
{hasResult &&
isSuccess &&
// 검색결과가 있을시
data?.pages.map((page) =>
page.content.map((post) => <PostCard {...post} key={post.postNo} />)
)}
{isSuccess && !hasResult && (
// 검색결과 없을 시
<Stack justifyContent="center" alignItems="center" py={8}>
<Image src={NoResult} alt="no result alert" />
</Stack>
)}
{/* 로딩창 */}
{isFetchingNextPage || isLoading ? (
<PostCardSkeleton />
) : (
// 인터섹션옵저버
hasNextPage && <div style={{ height: 60 }} ref={ref}></div>
)}
</div>
);
}

export default PopularPostCardList;
8 changes: 7 additions & 1 deletion client/src/const/serverPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ export const DELETE_COMMENT = (postPk: string, commentPk: string) =>
/**
* 게시물리스트를 받아오거나, 작성하는 Path 버전2 (Breaking Change)
*/
export const POST_LIST_V2 = "/posts/v2" as const;
export const POST_LIST_V2 = "/posts/v2";

/**
* 게시물리스트를 받아오거나, 작성하는 Path 버전2 (Breaking Change)
*/
export const POPULAR_POST_LIST = "/posts/popular";

/**
* ID(pk) 를 입력받아 해당 포스트를 지우는 URL
*/
Expand Down
127 changes: 127 additions & 0 deletions client/src/queries/post/useGetPopularPostListInfiniteQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query";
import { PostInterface } from "@/types/post/PostInterface";
import { AxiosRequestConfig } from "axios";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { POPULAR_POST_LIST } from "@/const/serverPath";
import useAxiosPrivate from "@/hooks/useAxiosPrivate";
import Pagenated from "@/types/Pagenated";

export interface UseGetPopularPostListQueryInterface
extends GetPostListOptions {
initialData?: AugmentedGetPostListResponse;
headers?: AxiosRequestConfig["headers"];
}

export const useGetPopularPostListInfiniteQuery = ({
initialData,
size,
sort,
headers,
}: UseGetPopularPostListQueryInterface) => {
return useInfiniteQuery({
queryKey: getPopularPostListInfiniteQueryKey.byKeyword({
sort,
}),

queryFn: async ({ pageParam = 0 }) =>
await getPopularPostListQueryFn({
page: pageParam,
size,
sort,
headers: headers?.Authorization
? headers
: { Authorization: getTokenFromLocalStorage() },
}),

getNextPageParam: ({
currentPage,
hasNextPage,
}: AugmentedGetPostListResponse) =>
hasNextPage ? currentPage + 1 : undefined,

getPreviousPageParam: ({ currentPage }: AugmentedGetPostListResponse) =>
currentPage > 0 ? currentPage - 1 : undefined,
initialPageParam: 0,
initialData: initialData
? { pages: [initialData], pageParams: [0] }
: undefined,
});
};
/**
* 포스트리스트를 받아올 때 Query string으로 사용되는 값
*/
export interface GetPostListOptions {
page?: number;
size?: number;
sort?: string;
}
/**
* 서버응답값 + 무한스크롤을 위해 증강된 값
*/
export interface AugmentedGetPostListResponse extends Pagenated<PostInterface> {
currentPage: number;
hasNextPage: boolean;
}

export const getPopularPostListQueryFn = async ({
page = 0,
size = 10,
sort,
headers,
}: GetPostListOptions & {
headers?: AxiosRequestConfig<any>["headers"];
}): Promise<AugmentedGetPostListResponse> => {
const axiosPrivate = useAxiosPrivate();
const { data } = await axiosPrivate.get<{ data: Pagenated<PostInterface> }>(
POPULAR_POST_LIST,
{
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
params: {
page,
size,
sort: sort ?? "lastModifiedDate,desc",
},
headers,
}
);
return {
...data.data,
currentPage: page,
hasNextPage: data.data.totalElements / ((page + 1) * size) > 1,
};
};

export interface PopularPostListInfiniteQueryKey {
keyword?: string;
userNo?: string;
sort?: string;
}

export const getPopularPostListInfiniteQueryKey = {
all: ["popular_posts"] as const,
byKeyword: ({ sort }: Omit<GetPostListOptions, "page" | "size">) =>
[
"popular_posts",
{
sort,
},
] as const,
};

/**
* 모든 포스트리스트 쿼리를 Invalidate 하는 Hooks
* @returns Invalidate 함수
*/
export const useInvalidatePopularPostList = () => {
/**
* 모든 포스트리스트 쿼리를 Invalidate 하는함수
*/
const queryClinet = useQueryClient();
return () => {
queryClinet.invalidateQueries({
queryKey: getPopularPostListInfiniteQueryKey.all,
});
};
};

export default useGetPopularPostListInfiniteQuery;

0 comments on commit 11f70db

Please sign in to comment.