diff --git a/package.json b/package.json index f25d7649..412515a1 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "dependencies": { "@hookform/resolvers": "^3.6.0", "@reduxjs/toolkit": "^2.2.5", + "@tanstack/react-query": "^5.48.0", + "@tanstack/react-query-devtools": "^5.48.0", "axios": "^1.7.2", "next": "14.2.4", "react": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6690bb31..4b0b3ec8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,12 @@ importers: '@reduxjs/toolkit': specifier: ^2.2.5 version: 2.2.5(react-redux@9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1))(react@18.3.1) + '@tanstack/react-query': + specifier: ^5.48.0 + version: 5.48.0(react@18.3.1) + '@tanstack/react-query-devtools': + specifier: ^5.48.0 + version: 5.48.0(@tanstack/react-query@5.48.0(react@18.3.1))(react@18.3.1) axios: specifier: ^1.7.2 version: 1.7.2 @@ -351,6 +357,23 @@ packages: '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + '@tanstack/query-core@5.48.0': + resolution: {integrity: sha512-lZAfPPeVIqXCswE9SSbG33B6/91XOWt/Iq41bFeWb/mnHwQSIfFRbkS4bfs+WhIk9abRArF9Id2fp0Mgo+hq6Q==} + + '@tanstack/query-devtools@5.47.0': + resolution: {integrity: sha512-oo10s7Nqaf/Q3QF4vuSwS0xw7zuYr5nXef4RHQIXVJKvRQeo9WowPLAnB0SF/voB0c4GTX6Vq8wfQ1G72ezEdw==} + + '@tanstack/react-query-devtools@5.48.0': + resolution: {integrity: sha512-0xvk8KDvEfQuLz3dy9jqtP0f6iR724d57Br7KtrtClbyqB53cy3Iy6BiTsiHaSsYnex/+cxWJZIX1UJWeV8Amw==} + peerDependencies: + '@tanstack/react-query': ^5.48.0 + react: ^18 || ^19 + + '@tanstack/react-query@5.48.0': + resolution: {integrity: sha512-GDExbjYWzvDokyRqMSWXdrPiYpp95Aig0oeMIrxTaruOJJgWiWfUP//OAaowm2RrRkGVsavSZdko/XmIrrV2Nw==} + peerDependencies: + react: ^18.0.0 + '@types/conventional-commits-parser@5.0.0': resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} @@ -2632,6 +2655,21 @@ snapshots: '@swc/counter': 0.1.3 tslib: 2.6.3 + '@tanstack/query-core@5.48.0': {} + + '@tanstack/query-devtools@5.47.0': {} + + '@tanstack/react-query-devtools@5.48.0(@tanstack/react-query@5.48.0(react@18.3.1))(react@18.3.1)': + dependencies: + '@tanstack/query-devtools': 5.47.0 + '@tanstack/react-query': 5.48.0(react@18.3.1) + react: 18.3.1 + + '@tanstack/react-query@5.48.0(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.48.0 + react: 18.3.1 + '@types/conventional-commits-parser@5.0.0': dependencies: '@types/node': 20.14.5 diff --git a/src/hooks/useFetchDashboards.ts b/src/hooks/useFetchDashboards.ts index c7524398..c8e38cc2 100644 --- a/src/hooks/useFetchDashboards.ts +++ b/src/hooks/useFetchDashboards.ts @@ -1,25 +1,29 @@ -import { useQuery } from 'react-query'; -import { useDispatch, useSelector } from 'react-redux'; +import { useQuery } from '@tanstack/react-query'; +import { useDispatch } from 'react-redux'; import { getDashboardsList } from '@/services/getService'; import { setDashboards } from '@/store/reducers/dashboardsSlice'; -const fetchDashboards = async () => { - const response = await getDashboardsList(); - - if (response.status !== 200) { - throw new Error('Failed to fetch dashboards'); - } - - return response.data; -}; - export const useFetchDashboards = () => { const dispatch = useDispatch(); - return useQuery('dashboards', () => fetchDashboards(), { - onSuccess: (data) => { - dispatch(setDashboards({ dashboards: data.dashboards, totalCount: data.totalCount })); + const { isLoading, error, data, isFetching } = useQuery({ + queryKey: ['dashboards'], // 쿼리 키는 문자열이나 배열로 지정할 수 있습니다 + queryFn: async () => { + try { + const response = await getDashboardsList(); + if (response.status !== 200) { + throw new Error('Failed to fetch dashboards'); + } + const data = response.data; + dispatch(setDashboards({ dashboards: data.dashboards, totalCount: data.totalCount })); + return data; // 데이터를 반환해야 합니다 + } catch (error) { + // 에러 처리 + throw new Error('데이터를 불러오는 중 에러 발생: ' + error); + } }, }); + + return { isLoading, error, data, isFetching }; }; diff --git a/src/hooks/useFetchData.ts b/src/hooks/useFetchData.ts index dac23972..72a33e66 100644 --- a/src/hooks/useFetchData.ts +++ b/src/hooks/useFetchData.ts @@ -1,16 +1,16 @@ -import { useQuery, QueryKey } from 'react-query'; - -const useFetchData = (queryKey: QueryKey, getService: () => Promise<{ data: T }>) => { - const fetchData = async () => { - const response = await getService(); - return response.data; - }; +import { useQuery, QueryKey, UseQueryResult } from '@tanstack/react-query'; +const useFetchData = (queryKey: QueryKey, getService: () => Promise<{ data: T }>): UseQueryResult => { return useQuery({ - queryKey, // 캐시 키를 임의로 지정할 수 있음 - queryFn: fetchData, // 비동기 getService 함수 (services/ 에 정의) - onError: (error: Error) => { - console.error('Error fetching data:', error); + queryKey: queryKey, + queryFn: async () => { + try { + const response = await getService(); + return response.data; + } catch (error) { + // 에러 처리 + throw new Error('데이터를 불러오는 중 에러 발생: ' + error); + } }, }); }; diff --git a/src/hooks/useSignIn.ts b/src/hooks/useSignIn.ts index 738ba8a2..2fa44638 100644 --- a/src/hooks/useSignIn.ts +++ b/src/hooks/useSignIn.ts @@ -1,4 +1,4 @@ -import { useMutation } from 'react-query'; +import { useMutation } from '@tanstack/react-query'; import { useDispatch } from 'react-redux'; import { postSignIn } from '@/services/postService'; @@ -8,15 +8,8 @@ import { SignInForm, SignInResponse } from '@/types/post/SignInForm.interface'; export const useSignIn = () => { const dispatch = useDispatch(); - return useMutation(postSignIn, { - onMutate: () => { - dispatch(isLoading(true)); - dispatch(setError(null)); - }, - onSuccess: (data) => { - dispatch(setUser(data)); - dispatch(isLoading(false)); - }, + return useMutation({ + mutationFn: postSignIn, onError: (error: unknown) => { if (error instanceof Error) { dispatch(setError(error.message)); @@ -25,5 +18,15 @@ export const useSignIn = () => { } dispatch(isLoading(false)); }, + onSuccess: (data) => { + dispatch(setUser(data)); + dispatch(isLoading(false)); + }, + onMutate: async () => { + dispatch(isLoading(true)); + dispatch(setError(null)); + // 이 부분에서 필요한 경우 이전 상태를 저장하거나 다른 작업을 수행할 수 있음 + return null; // 반환 값은 나중에 revert 함수에서 사용할 수 있음 + }, }); }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index ebd75c22..35c08840 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,6 +1,7 @@ import '@/styles/globals.css'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import type { AppProps } from 'next/app'; -import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; @@ -17,6 +18,7 @@ export default function App({ Component, pageProps }: AppProps) { +