From 74598ac382a066f1439dbafd623a7484e3743dc1 Mon Sep 17 00:00:00 2001 From: Hyejun Lee Date: Mon, 6 Nov 2023 16:52:36 +0900 Subject: [PATCH] =?UTF-8?q?[SP2]=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20useQuery=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F?= =?UTF-8?q?=20=ED=95=84=ED=84=B0=EB=A7=81=20=EA=B0=92=20=EC=9C=A0=EC=A7=80?= =?UTF-8?q?=20(#256)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: queryClient 기본값 설정 * feat: 프로젝트 리스트 API 반환 타입 수정 * feat: 프로젝트 리스트 API useQuery 적용 * feat: 서스펜스 Fallback UI 컴포넌트 생성 * style: 프로젝트 카드 스타일 코드 수정 * style: 프로젝트 개수 스타일 코드 수정 * style: 프로젝트 목록 스타일 코드 수정 * feat: 프로젝트 필터값 세션 스토리지 저장 * feat: 최근 출시한 프로젝트 캐싱 데이터 사용 * feat: 프로젝트 목록 staleTime 지정 * feat: 세션 스토리지 훅 타입 지정 * style: Fallback UI 수정 * fix: 최근 출시한 프로젝트 useQuery 적용 * style: 필요없는 스타일 코드 제거 * feat : 프로젝트 캐러셀 SkeletonUI (#258) * fix: 블로그 썸네일 옵셔널 체이닝 적용 --------- Co-authored-by: solar3070 <> Co-authored-by: wooyoung <62867581+f0rever0@users.noreply.github.com> --- src/lib/api/remote/project.ts | 13 +- src/lib/types/project.ts | 6 +- src/pages/_app.tsx | 17 +- .../BlogPage/components/BlogPost/index.tsx | 2 +- src/views/ProjectPage/ProjectPage.tsx | 29 ++- .../RecentProjectList/Item/style.ts | 7 +- .../RecentProjectListSkeletonUI/index.tsx | 40 ++++ .../RecentProjectListSkeletonUI/style.ts | 178 ++++++++++++++++++ .../components/RecentProjectList/index.tsx | 40 ++-- .../components/project/ProjectCard/index.tsx | 60 +++--- .../components/project/ProjectCard/style.ts | 30 +-- .../project/ProjectCardList/index.tsx | 21 +-- .../project/ProjectCardList/style.ts | 6 - .../components/project/ProjectList.tsx | 55 ++---- .../project/ProjectListCount/index.tsx | 5 +- .../project/ProjectListCount/style.ts | 6 + .../ProjectCardSkeletonUI/index.tsx | 0 .../ProjectCardSkeletonUI/style.ts | 10 +- .../project/ProjectListFallback/index.tsx | 13 ++ .../project/ProjectListFallback/style.ts | 27 +++ .../ProjectPage/components/project/style.ts | 8 - src/views/ProjectPage/hooks/queries/index.ts | 16 ++ src/views/ProjectPage/hooks/useFetch.ts | 22 --- .../ProjectPage/hooks/useInfiniteScroll.ts | 23 --- src/views/ProjectPage/styles.ts | 4 + 25 files changed, 413 insertions(+), 225 deletions(-) create mode 100644 src/views/ProjectPage/components/RecentProjectList/RecentProjectListSkeletonUI/index.tsx create mode 100644 src/views/ProjectPage/components/RecentProjectList/RecentProjectListSkeletonUI/style.ts rename src/views/ProjectPage/components/project/{ => ProjectListFallback}/ProjectCardSkeletonUI/index.tsx (100%) rename src/views/ProjectPage/components/project/{ => ProjectListFallback}/ProjectCardSkeletonUI/style.ts (90%) create mode 100644 src/views/ProjectPage/components/project/ProjectListFallback/index.tsx create mode 100644 src/views/ProjectPage/components/project/ProjectListFallback/style.ts create mode 100644 src/views/ProjectPage/hooks/queries/index.ts delete mode 100644 src/views/ProjectPage/hooks/useFetch.ts delete mode 100644 src/views/ProjectPage/hooks/useInfiniteScroll.ts diff --git a/src/lib/api/remote/project.ts b/src/lib/api/remote/project.ts index 0cc85914..9782c6cd 100644 --- a/src/lib/api/remote/project.ts +++ b/src/lib/api/remote/project.ts @@ -1,18 +1,15 @@ -import { BASE_URL, DEFAULT_TIMEOUT } from '@src/lib/constants/client'; +import { BASE_URL } from '@src/lib/constants/client'; import axios from 'axios'; import qs from 'qs'; import { GetProjectDetailResponse, - GetProjectListResponse, ProjectAPI, ProjectCategoryType, ProjectPlatformType, + ProjectType, } from '../../types/project'; -const client = axios.create({ - baseURL: BASE_URL, - timeout: DEFAULT_TIMEOUT, -}); +const client = axios.create({ baseURL: BASE_URL }); const getProjectDetail = async (projectId: number): Promise => { const { data } = await client.get(`/projects/${projectId}`); @@ -26,12 +23,12 @@ const getProjectDetail = async (projectId: number): Promise => { +): Promise => { const categoryParameter = category === ProjectCategoryType.ALL ? {} : { filter: category }; const platformParameter = platform === ProjectPlatformType.ALL ? {} : { platform }; const parameter = qs.stringify({ ...categoryParameter, ...platformParameter }); const { data } = await client.get(`/projects?${parameter}`); - return { projects: data }; + return data; }; export const remoteProjectAPI: ProjectAPI = { diff --git a/src/lib/types/project.ts b/src/lib/types/project.ts index 1e2360bc..e276a387 100644 --- a/src/lib/types/project.ts +++ b/src/lib/types/project.ts @@ -56,14 +56,10 @@ export interface GetProjectDetailResponse { project: ProjectType; } -export interface GetProjectListResponse { - projects: ProjectType[]; -} - export interface ProjectAPI { getProjectDetail(projectId: number): Promise; getProjectList( category: ProjectCategoryType, platform: ProjectPlatformType, - ): Promise; + ): Promise; } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 841da6a6..be5a26a9 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -4,8 +4,8 @@ import Head from 'next/head'; import { useRouter } from 'next/router'; import { Global } from '@emotion/react'; import { useEffect } from 'react'; -import { useState } from 'react'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { ReactQueryDevtools } from 'react-query/devtools'; import SEO from '@src/components/common/SEO'; import GoogleTagManagerNoscript from '@src/components/googleTagManager/Noscript'; import GoogleTagManagerScript from '@src/components/googleTagManager/Script'; @@ -14,6 +14,18 @@ import { AMPLITUDE_API_KEY } from '@src/lib/constants/client'; import { global } from '@src/lib/styles/global'; import { pageViewTrackingEnrichment } from '@src/lib/utils/pageViewTrackingEnrichment'; +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + suspense: true, + refetchOnWindowFocus: false, + refetchOnMount: false, + refetchOnReconnect: false, + }, + }, +}); + amplitude.add(pageViewTrackingEnrichment()); amplitude.init(AMPLITUDE_API_KEY, { logLevel: amplitude.Types.LogLevel.Warn, @@ -21,8 +33,6 @@ amplitude.init(AMPLITUDE_API_KEY, { }); function MyApp({ Component, pageProps }: AppProps) { - const [queryClient] = useState(() => new QueryClient()); - const router = useRouter(); useEffect(() => { router.events.on('routeChangeComplete', gtm.pageview); @@ -76,6 +86,7 @@ function MyApp({ Component, pageProps }: AppProps) { + diff --git a/src/views/BlogPage/components/BlogPost/index.tsx b/src/views/BlogPage/components/BlogPost/index.tsx index 760db823..88ff0e77 100644 --- a/src/views/BlogPage/components/BlogPost/index.tsx +++ b/src/views/BlogPage/components/BlogPost/index.tsx @@ -51,7 +51,7 @@ export default function BlogPost({ selectedTap, blogPost }: BlogPostProps) { (ProjectCategoryType.ALL); - const [selectedPlatform, setPlatform] = useState(ProjectPlatformType.ALL); - - const state = useFetch(selectedCategory, selectedPlatform); - const isMobile = useIsMobile('899px'); + const [selectedCategory, setCategory] = useStorage( + 'projectCategory', + 'sessionStorage', + ProjectCategoryType.ALL, + ); + const [selectedPlatform, setPlatform] = useStorage( + 'projectPlatform', + 'sessionStorage', + ProjectPlatformType.ALL, + ); return ( - SOPT{!isMobile && '에서 진행된'} 프로젝트 둘러보기 + + SOPT에서 진행된 프로젝트 둘러보기 +