Refactor: hooks 리팩토링

This commit is contained in:
정현조 2024-09-12 10:43:00 +09:00
parent 3e7981d8ba
commit 4aa1dee1e9
3 changed files with 93 additions and 210 deletions

View File

@ -2,55 +2,25 @@ import { useQuery, UseQueryResult, useMutation, useQueryClient, UseMutationResul
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import useAuthStore from '@/stores/useAuthStore'; import useAuthStore from '@/stores/useAuthStore';
import { reissueTokenApi, fetchProfileApi } from '@/api/authApi'; import { reissueTokenApi, fetchProfileApi } from '@/api/authApi';
import { SuccessResponse, RefreshTokenResponseDTO, MemberResponseDTO, CustomError } from '@/types';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
interface TokenResponse { export const useReissueToken = (): UseMutationResult<
status: number; SuccessResponse<RefreshTokenResponseDTO>,
code: number; AxiosError<CustomError>
message: string; > => {
data: {
accessToken: string;
};
errors: Array<{
field: string;
code: string;
message: string;
objectName: string;
}>;
isSuccess: boolean;
}
interface ProfileResponse {
status: number;
code: number;
message: string;
data: {
id: number;
nickname: string;
profileImage: string;
};
errors: Array<{
field: string;
code: string;
message: string;
objectName: string;
}>;
isSuccess: boolean;
}
interface ErrorResponse {
message: string;
}
export const useReissueToken = (): UseMutationResult<TokenResponse, AxiosError<ErrorResponse>> => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { setLoggedIn } = useAuthStore(); const { setLoggedIn } = useAuthStore();
return useMutation({ return useMutation({
mutationFn: reissueTokenApi, mutationFn: reissueTokenApi,
onSuccess: (data) => { onSuccess: (data) => {
if (data.isSuccess && data.data) {
setLoggedIn(true, data.data.accessToken); setLoggedIn(true, data.data.accessToken);
queryClient.invalidateQueries({ queryKey: ['profile'] }); queryClient.invalidateQueries({ queryKey: ['profile'] });
} else {
console.error('토큰 재발급 응답 오류:', data.message);
}
}, },
onError: (error) => { onError: (error) => {
console.error('토큰 재발급 실패:', error?.response?.data?.message || '알 수 없는 오류'); console.error('토큰 재발급 실패:', error?.response?.data?.message || '알 수 없는 오류');
@ -58,24 +28,23 @@ export const useReissueToken = (): UseMutationResult<TokenResponse, AxiosError<E
}); });
}; };
export const useProfile = (): UseQueryResult<ProfileResponse, AxiosError<ErrorResponse>> => { export const useProfile = (): UseQueryResult<SuccessResponse<MemberResponseDTO>, AxiosError<CustomError>> => {
const { accessToken, setProfile } = useAuthStore(); const { accessToken, setProfile } = useAuthStore();
return useQuery<ProfileResponse, AxiosError<ErrorResponse>>({ const query = useQuery<SuccessResponse<MemberResponseDTO>, AxiosError<CustomError>>({
queryKey: ['profile'], queryKey: ['profile'],
queryFn: fetchProfileApi, queryFn: fetchProfileApi,
enabled: !!accessToken, enabled: !!accessToken,
select: (data) => { select: (data) => data,
if (data.isSuccess) {
setProfile({
id: data.data.id,
nickname: data.data.nickname,
profileImage: data.data.profileImage,
}); });
useEffect(() => {
if (query.data?.isSuccess) {
setProfile(query.data.data);
} }
return data; }, [query.data, setProfile]);
},
}); return query;
}; };
export const useFetchProfile = () => { export const useFetchProfile = () => {
@ -83,22 +52,20 @@ export const useFetchProfile = () => {
const [isFetched, setIsFetched] = useState(false); const [isFetched, setIsFetched] = useState(false);
useEffect(() => { useEffect(() => {
if (!profile.id && !isFetched) { if (!profile && !isFetched) {
fetchProfileApi() fetchProfileApi()
.then((data) => { .then((data) => {
if (data?.isSuccess && data.data) { if (data.isSuccess && data.data) {
setProfile({ setProfile(data.data);
id: data.data.id,
nickname: data.data.nickname,
profileImage: data.data.profileImage,
});
setIsFetched(true); setIsFetched(true);
} else {
console.error('프로필 응답 오류:', data.message);
} }
}) })
.catch((error) => { .catch((error: AxiosError<CustomError>) => {
alert('프로필을 가져오는 중 오류가 발생했습니다. 다시 시도해주세요.'); alert('프로필을 가져오는 중 오류가 발생했습니다. 다시 시도해주세요.');
console.error('프로필 가져오기 실패:', error); console.error('프로필 가져오기 실패:', error?.response?.data?.message || '알 수 없는 오류');
}); });
} }
}, [profile.id, setProfile, isFetched]); }, [profile, setProfile, isFetched]);
}; };

View File

@ -9,80 +9,46 @@ import {
addProjectMemberApi, addProjectMemberApi,
removeProjectMemberApi, removeProjectMemberApi,
} from '@/api/projectApi'; } from '@/api/projectApi';
import { BaseResponse, ProjectResponseDTO, ProjectListResponseDTO, CustomError } from '@/types';
interface Project {
id: number;
title: string;
workspaceId: number;
projectType: string;
createdAt: string;
updatedAt: string;
}
interface ProjectsResponse {
status: number;
code: number;
message: string;
data: {
workspaceResponses: Project[];
};
errors: Array<{
field: string;
code: string;
message: string;
objectName: string;
}>;
isSuccess: boolean;
}
interface ErrorResponse {
message: string;
}
export const useGetProject = ( export const useGetProject = (
projectId: number, projectId: number,
memberId: number memberId: number
): UseQueryResult<ProjectsResponse, AxiosError<ErrorResponse>> => { ): UseQueryResult<BaseResponse<ProjectResponseDTO>, AxiosError<CustomError>> => {
return useQuery<ProjectsResponse, AxiosError<ErrorResponse>>({ return useQuery<BaseResponse<ProjectResponseDTO>, AxiosError<CustomError>>({
queryKey: ['project', projectId], queryKey: ['project', projectId],
queryFn: () => getProjectApi(projectId, memberId), queryFn: () => getProjectApi(projectId, memberId),
}); });
}; };
export const useUpdateProject = (): UseMutationResult< export const useUpdateProject = (): UseMutationResult<
ProjectsResponse, BaseResponse<ProjectResponseDTO>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ projectId: number; memberId: number; data: { title: string; projectType: string } } {
projectId: number;
memberId: number;
data: { title: string; projectType: 'classification' | 'detection' | 'segmentation' };
}
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ projectId, memberId, data }) => updateProjectApi(projectId, memberId, data), mutationFn: ({ projectId, memberId, data }) => updateProjectApi(projectId, memberId, data),
onSuccess: (data) => { onSuccess: (data) => {
const project = data.data?.workspaceResponses?.[0]; queryClient.invalidateQueries({ queryKey: ['project', data.data.id] });
if (project) {
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
} else {
console.error('프로젝트 데이터가 없습니다.');
}
}, },
}); });
}; };
export const useDeleteProject = (): UseMutationResult< export const useDeleteProject = (): UseMutationResult<
ProjectsResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ projectId: number; memberId: number } { projectId: number; memberId: number }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ projectId, memberId }) => deleteProjectApi(projectId, memberId), mutationFn: ({ projectId, memberId }) => deleteProjectApi(projectId, memberId),
onSuccess: (data) => { onSuccess: (_, variables) => {
const project = data.data?.workspaceResponses?.[0]; queryClient.invalidateQueries({ queryKey: ['project', variables.projectId] });
if (project) {
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
} else {
console.error('프로젝트 데이터가 없습니다.');
}
}, },
}); });
}; };
@ -90,61 +56,59 @@ export const useDeleteProject = (): UseMutationResult<
export const useGetAllProjects = ( export const useGetAllProjects = (
workspaceId: number, workspaceId: number,
memberId: number, memberId: number,
lastProjectId?: number, options?: { enabled: boolean }
limit: number = 10 ): UseQueryResult<BaseResponse<ProjectListResponseDTO>, AxiosError<CustomError>> => {
): UseQueryResult<ProjectsResponse, AxiosError<ErrorResponse>> => { return useQuery<BaseResponse<ProjectListResponseDTO>, AxiosError<CustomError>>({
return useQuery<ProjectsResponse, AxiosError<ErrorResponse>>({
queryKey: ['projects', workspaceId], queryKey: ['projects', workspaceId],
queryFn: () => getAllProjectsApi(workspaceId, memberId, lastProjectId, limit), queryFn: () => getAllProjectsApi(workspaceId, memberId),
enabled: options?.enabled,
}); });
}; };
export const useCreateProject = (): UseMutationResult< export const useCreateProject = (): UseMutationResult<
ProjectsResponse, BaseResponse<ProjectResponseDTO>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ workspaceId: number; memberId: number; data: { title: string; projectType: string } } {
workspaceId: number;
memberId: number;
data: { title: string; projectType: 'classification' | 'detection' | 'segmentation' };
}
> => { > => {
const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ workspaceId, memberId, data }) => createProjectApi(workspaceId, memberId, data), mutationFn: ({ workspaceId, memberId, data }) => createProjectApi(workspaceId, memberId, data),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['projects', variables.workspaceId] });
},
}); });
}; };
export const useAddProjectMember = (): UseMutationResult< export const useAddProjectMember = (): UseMutationResult<
ProjectsResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ projectId: number; memberId: number; newMemberId: number; privilegeType: string } { projectId: number; memberId: number; newMemberId: number; privilegeType: string }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ projectId, memberId, newMemberId, privilegeType }) => mutationFn: ({ projectId, memberId, newMemberId, privilegeType }) =>
addProjectMemberApi(projectId, memberId, newMemberId, privilegeType), addProjectMemberApi(projectId, memberId, newMemberId, privilegeType),
onSuccess: (data) => { onSuccess: (_, variables) => {
const project = data.data?.workspaceResponses?.[0]; queryClient.invalidateQueries({ queryKey: ['project', variables.projectId] });
if (project) {
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
} else {
console.error('프로젝트 데이터가 없습니다.');
}
}, },
}); });
}; };
export const useRemoveProjectMember = (): UseMutationResult< export const useRemoveProjectMember = (): UseMutationResult<
ProjectsResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ projectId: number; memberId: number; targetMemberId: number } { projectId: number; memberId: number; targetMemberId: number }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ projectId, memberId, targetMemberId }) => mutationFn: ({ projectId, memberId, targetMemberId }) =>
removeProjectMemberApi(projectId, memberId, targetMemberId), removeProjectMemberApi(projectId, memberId, targetMemberId),
onSuccess: (data) => { onSuccess: (_, variables) => {
const project = data.data?.workspaceResponses?.[0]; queryClient.invalidateQueries({ queryKey: ['project', variables.projectId] });
if (project) {
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
} else {
console.error('프로젝트 데이터가 없습니다.');
}
}, },
}); });
}; };

View File

@ -9,90 +9,42 @@ import {
addWorkspaceMemberApi, addWorkspaceMemberApi,
removeWorkspaceMemberApi, removeWorkspaceMemberApi,
} from '@/api/workspaceApi'; } from '@/api/workspaceApi';
import { BaseResponse, WorkspaceResponseDTO, WorkspaceListResponseDTO, CustomError } from '@/types';
interface WorkspaceResponse {
status: number;
code: number;
message: string;
data: {
id: number;
memberId: string;
title: string;
content: string;
createdAt: string;
updatedAt: string;
};
errors: Array<{
field: string;
code: string;
message: string;
objectName: string;
}>;
isSuccess: boolean;
}
interface Workspace {
id: number;
memberId: string;
title: string;
content: string;
createdAt: string;
updatedAt: string;
}
interface GetAllWorkspacesResponse {
status: number;
code: number;
message: string;
data: {
workspaceResponses: Workspace[];
};
errors: Array<{
field: string;
code: string;
message: string;
objectName: string;
}>;
isSuccess: boolean;
}
interface ErrorResponse {
message: string;
}
export const useGetWorkspace = ( export const useGetWorkspace = (
workspaceId: number, workspaceId: number,
memberId: number memberId: number
): UseQueryResult<WorkspaceResponse, AxiosError<ErrorResponse>> => { ): UseQueryResult<BaseResponse<WorkspaceResponseDTO>, AxiosError<CustomError>> => {
return useQuery<WorkspaceResponse, AxiosError<ErrorResponse>>({ return useQuery<BaseResponse<WorkspaceResponseDTO>, AxiosError<CustomError>>({
queryKey: ['workspace', workspaceId], queryKey: ['workspace', workspaceId],
queryFn: () => getWorkspaceApi(workspaceId, memberId), queryFn: () => getWorkspaceApi(workspaceId, memberId),
}); });
}; };
export const useUpdateWorkspace = (): UseMutationResult< export const useUpdateWorkspace = (): UseMutationResult<
WorkspaceResponse, BaseResponse<WorkspaceResponseDTO>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ workspaceId: number; memberId: number; data: { title: string; content: string } } { workspaceId: number; memberId: number; data: { title: string; content: string } }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ workspaceId, memberId, data }) => updateWorkspaceApi(workspaceId, memberId, data), mutationFn: ({ workspaceId, memberId, data }) => updateWorkspaceApi(workspaceId, memberId, data),
onSuccess: () => { onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['workspace'] }); queryClient.invalidateQueries({ queryKey: ['workspace', variables.workspaceId] });
}, },
}); });
}; };
export const useDeleteWorkspace = (): UseMutationResult< export const useDeleteWorkspace = (): UseMutationResult<
WorkspaceResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ workspaceId: number; memberId: number } { workspaceId: number; memberId: number }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ workspaceId, memberId }) => deleteWorkspaceApi(workspaceId, memberId), mutationFn: ({ workspaceId, memberId }) => deleteWorkspaceApi(workspaceId, memberId),
onSuccess: () => { onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['workspace'] }); queryClient.invalidateQueries({ queryKey: ['workspace', variables.workspaceId] });
}, },
}); });
}; };
@ -101,52 +53,52 @@ export const useGetAllWorkspaces = (
memberId: number, memberId: number,
lastWorkspaceId?: number, lastWorkspaceId?: number,
limit?: number limit?: number
): UseQueryResult<GetAllWorkspacesResponse, AxiosError<ErrorResponse>> => { ): UseQueryResult<BaseResponse<WorkspaceListResponseDTO>, AxiosError<CustomError>> => {
return useQuery<GetAllWorkspacesResponse, AxiosError<ErrorResponse>>({ return useQuery<BaseResponse<WorkspaceListResponseDTO>, AxiosError<CustomError>>({
queryKey: ['workspaces'], queryKey: ['workspaces'],
queryFn: () => getAllWorkspacesApi(memberId, lastWorkspaceId, limit), queryFn: () => getAllWorkspacesApi(memberId, lastWorkspaceId, limit),
}); });
}; };
export const useCreateWorkspace = (): UseMutationResult< export const useCreateWorkspace = (): UseMutationResult<
WorkspaceResponse, BaseResponse<WorkspaceResponseDTO>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ memberId: number; data: { title: string; content: string } } { memberId: number; data: { title: string; content: string } }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ memberId, data }) => createWorkspaceApi(memberId, data), mutationFn: ({ memberId, data }) => createWorkspaceApi(memberId, data),
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['workspace'] }); queryClient.invalidateQueries({ queryKey: ['workspaces'] });
}, },
}); });
}; };
export const useAddWorkspaceMember = (): UseMutationResult< export const useAddWorkspaceMember = (): UseMutationResult<
WorkspaceResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ workspaceId: number; memberId: number; newMemberId: number } { workspaceId: number; memberId: number; newMemberId: number }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ workspaceId, memberId, newMemberId }) => addWorkspaceMemberApi(workspaceId, memberId, newMemberId), mutationFn: ({ workspaceId, memberId, newMemberId }) => addWorkspaceMemberApi(workspaceId, memberId, newMemberId),
onSuccess: () => { onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['workspace'] }); queryClient.invalidateQueries({ queryKey: ['workspace', variables.workspaceId] });
}, },
}); });
}; };
export const useRemoveWorkspaceMember = (): UseMutationResult< export const useRemoveWorkspaceMember = (): UseMutationResult<
WorkspaceResponse, BaseResponse<null>,
AxiosError<ErrorResponse>, AxiosError<CustomError>,
{ workspaceId: number; memberId: number; targetMemberId: number } { workspaceId: number; memberId: number; targetMemberId: number }
> => { > => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: ({ workspaceId, memberId, targetMemberId }) => mutationFn: ({ workspaceId, memberId, targetMemberId }) =>
removeWorkspaceMemberApi(workspaceId, memberId, targetMemberId), removeWorkspaceMemberApi(workspaceId, memberId, targetMemberId),
onSuccess: () => { onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['workspace'] }); queryClient.invalidateQueries({ queryKey: ['workspace', variables.workspaceId] });
}, },
}); });
}; };