From 1d5a01c94d005ef530adf5811f4ec5d952a6b540 Mon Sep 17 00:00:00 2001 From: ParkGeunCheol <72205402+GC-Park@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:40:46 +0900 Subject: [PATCH] =?UTF-8?q?[FE]=20Refactor/#643:=20Profile=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20API=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20React-Query=20=EC=A0=81=EC=9A=A9=20(#64?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: http 모듈 추가 * feat: Profile get api 추가 * feat: useProfileList hook 추가 * refactor: fetchGet을 useProfileList로 변경 * refactor: getProfile api에 url 직접 입력으로 변경 * refactor: 사용하지 않는 매개 변수 삭제 및 queryFn 수정 * refactor: 필요없는 코드 삭제 * refactor: query refetch 추가 * refactor: tanstack query 기본 설정 추가 * refactor: profile리스트 가져오는 부분 query 추가 및 필요없는 코드 삭제 * refactor: useQuery를 useSuspenseQuery로 변경 * refactor: Profile에 Query suspense 적용 --- frontend/src/apis/Patrick/http.ts | 36 +++++++++++++++++++ frontend/src/apis/Patrick/index.ts | 6 ++++ .../src/components/TopicCardList/index.tsx | 19 +++------- frontend/src/hooks/queries/useProfileList.ts | 13 +++++++ frontend/src/index.tsx | 17 +++++---- frontend/src/router.tsx | 5 +-- 6 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 frontend/src/apis/Patrick/http.ts create mode 100644 frontend/src/apis/Patrick/index.ts create mode 100644 frontend/src/hooks/queries/useProfileList.ts diff --git a/frontend/src/apis/Patrick/http.ts b/frontend/src/apis/Patrick/http.ts new file mode 100644 index 00000000..49926b83 --- /dev/null +++ b/frontend/src/apis/Patrick/http.ts @@ -0,0 +1,36 @@ +import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; + +const API_PREFIX = 'api'; + +export const BASE_URL = + process.env.APP_URL || `https://mapbefine.com/${API_PREFIX}`; + +const axiosInstance = axios.create({ + baseURL: BASE_URL, + timeout: 5000, +}); + +export interface HttpClient extends AxiosInstance { + get(url: string, config?: AxiosRequestConfig): Promise; + post( + url: string, + data?: any, + config?: AxiosRequestConfig, + ): Promise; + patch( + url: string, + data?: any, + config?: AxiosRequestConfig, + ): Promise; + put( + url: string, + data?: any, + config?: AxiosRequestConfig, + ): Promise; + delete(url: string, config?: AxiosRequestConfig): Promise; +} + +export const http: HttpClient = axiosInstance; + +// axios.interceptors.request.use() +axios.interceptors.response.use((res) => res.data) diff --git a/frontend/src/apis/Patrick/index.ts b/frontend/src/apis/Patrick/index.ts new file mode 100644 index 00000000..5fbe65b5 --- /dev/null +++ b/frontend/src/apis/Patrick/index.ts @@ -0,0 +1,6 @@ +import { http } from './http'; +import { TopicCardProps } from '../../types/Topic'; + +export const getProfile = () => { + return http.get("/members/my/topics"); +}; diff --git a/frontend/src/components/TopicCardList/index.tsx b/frontend/src/components/TopicCardList/index.tsx index 66674998..b8c2643f 100644 --- a/frontend/src/components/TopicCardList/index.tsx +++ b/frontend/src/components/TopicCardList/index.tsx @@ -1,7 +1,6 @@ -import { Fragment, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { styled } from 'styled-components'; -import useGet from '../../apiHooks/useGet'; import { TopicCardProps } from '../../types/Topic'; import Button from '../common/Button'; import Flex from '../common/Flex'; @@ -9,6 +8,7 @@ import Grid from '../common/Grid'; import Space from '../common/Space'; import Text from '../common/Text'; import TopicCard from '../TopicCard'; +import useProfileList from '../../hooks/queries/useProfileList'; interface TopicCardListProps { url: string; @@ -27,18 +27,7 @@ function TopicCardList({ routePage, children, }: TopicCardListProps) { - const [topics, setTopics] = useState(null); - const { fetchGet } = useGet(); - - const getTopicsFromServer = async () => { - fetchGet(url, errorMessage, (response) => { - setTopics(response); - }); - }; - - useEffect(() => { - getTopicsFromServer(); - }, []); + const { data: topics, refetch: refetchTopic } = useProfileList(); if (!topics) return null; @@ -88,7 +77,7 @@ function TopicCardList({ bookmarkCount={topic.bookmarkCount} isInAtlas={topic.isInAtlas} isBookmarked={topic.isBookmarked} - getTopicsFromServer={getTopicsFromServer} + getTopicsFromServer={refetchTopic} /> ))} diff --git a/frontend/src/hooks/queries/useProfileList.ts b/frontend/src/hooks/queries/useProfileList.ts new file mode 100644 index 00000000..cfa066fb --- /dev/null +++ b/frontend/src/hooks/queries/useProfileList.ts @@ -0,0 +1,13 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; +import { getProfile } from '../../apis/Patrick'; + +const useProfileList = () => { + const { data, refetch } = useSuspenseQuery({ + queryKey: ['profileList'], + queryFn: getProfile, + }); + + return { data, refetch }; +}; + +export default useProfileList; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index d2999a20..ba31e7ac 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,6 +1,7 @@ import ReactDOM from 'react-dom/client'; import ReactGA from 'react-ga4'; import { ThemeProvider } from 'styled-components'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import App from './App'; import ErrorBoundary from './components/ErrorBoundary'; @@ -12,6 +13,8 @@ const rootElement = document.getElementById('root'); if (!rootElement) throw new Error('Failed to find the root element'); const root = ReactDOM.createRoot(rootElement); +const queryClient = new QueryClient(); + // if (process.env.NODE_ENV === 'development') { // const { worker } = require('./mocks/browser'); // worker.start({ quiet: true }); @@ -22,10 +25,12 @@ if (process.env.REACT_APP_GOOGLE_ANALYTICS) { } root.render( - - - - - - , + + + + + + + + , ); diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index dd9b8268..b2f5f13b 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -6,6 +6,7 @@ import Home from './pages/Home'; import NotFound from './pages/NotFound'; import RootPage from './pages/RootPage'; import Search from './pages/Search'; +import TopicListSkeleton from './components/Skeletons/TopicListSkeleton'; const SelectedTopic = lazy(() => import('./pages/SelectedTopic')); const NewPin = lazy(() => import('./pages/NewPin')); @@ -115,9 +116,9 @@ const routes: routeElement[] = [ { path: 'my-page', element: ( - + }> - + ), withAuth: true, },