-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* New : 인기 게시글을 불러오는 Server path 추가 * New : 인기게시글을 불러오는 쿼리 추가 * New : 인기 게시글 불러오기 기능 추가
- Loading branch information
1 parent
0c567b1
commit 11f70db
Showing
4 changed files
with
204 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
client/src/queries/post/useGetPopularPostListInfiniteQuery.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |