diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index a1c205739..35671b167 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -21,7 +21,7 @@ type RequestInitWithMethod = Omit & {method: Method}; type HeadersType = [string, string][] | Record | Headers; -export type Body = BodyInit | object | null; +export type Body = BodyInit | object | null; //init안에 FormDATA있음. type RequestProps = { baseUrl?: string; @@ -32,6 +32,12 @@ type RequestProps = { method: Method; }; +type CreateRequestInitProps = { + body?: Body; + method: Method; + headers?: HeadersType; +}; + type RequestMethodProps = Omit; type FetchType = { @@ -85,17 +91,26 @@ const prepareRequest = ({baseUrl = API_BASE_URL, method, endpoint, headers, body if (queryParams) url += `?${objectToQueryString(queryParams)}`; + const requestInit = createRequestInit({method, headers, body}); + + return {url, requestInit}; +}; + +const createRequestInit = ({method, headers, body}: CreateRequestInitProps) => { const requestInit: RequestInitWithMethod = { credentials: 'include', - headers: { - 'Content-Type': 'application/json', - ...headers, - }, method, - body: body ? JSON.stringify(body) : null, }; - return {url, requestInit}; + if (body instanceof FormData) { + return {...requestInit, body}; + } else { + return { + ...requestInit, + headers: {...headers, 'Content-Type': 'application/json'}, + body: body ? JSON.stringify(body) : null, + }; + } }; const executeRequest = async ({url, requestInit, errorHandlingStrategy}: WithErrorHandlingStrategy) => { @@ -114,7 +129,7 @@ const executeRequest = async ({url, requestInit, errorHandlingStrategy}: WithErr return response; } catch (error) { if (error instanceof Error) { - throw error; // 그대로 RequestError 또는 Error 인스턴스를 던집니다. + throw error; } throw error; diff --git a/client/src/apis/request/images.ts b/client/src/apis/request/images.ts index b881ee3ac..e17061c3c 100644 --- a/client/src/apis/request/images.ts +++ b/client/src/apis/request/images.ts @@ -10,26 +10,7 @@ export interface RequestPostImages { } export const requestPostImages = async ({eventId, formData}: WithEventId) => { - // return await requestPostWithoutResponse({ - // baseUrl: BASE_URL.HD, - // endpoint: `${ADMIN_API_PREFIX}/${eventId}/images`, - // headers: { - // 'Content-Type': 'multipart/form-data', - // }, - // body: formData, - // }); - - // TODO: (@todari): 기존의 request 방식들은 기본적으로 - // header를 Content-Type : application/json 으로 보내주고 있음 - // multipart/form-data 요청을 보내기 위해선 header Content-Type을 빈 객체로 전달해야 함 - fetch(`${BASE_URL.HD}${ADMIN_API_PREFIX}/${eventId}/images`, { - credentials: 'include', - // headers: { - // 'Content-Type': 'multipart/form-data', - // }, - method: 'POST', - body: formData, - }); + await requestPostWithoutResponse({endpoint: `${ADMIN_API_PREFIX}/${eventId}/images`, body: formData}); }; export const requestGetImages = async ({eventId}: WithEventId) => { diff --git a/client/src/hooks/queries/images/useRequestPostImages.ts b/client/src/hooks/queries/images/useRequestPostImages.ts index 619989694..fa49463e7 100644 --- a/client/src/hooks/queries/images/useRequestPostImages.ts +++ b/client/src/hooks/queries/images/useRequestPostImages.ts @@ -10,14 +10,14 @@ const useRequestPostImages = () => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); - const {mutate, ...rest} = useMutation({ + const {mutateAsync, ...rest} = useMutation({ mutationFn: ({formData}: RequestPostImages) => requestPostImages({eventId, formData}), onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.images]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.images]}); }, }); - return {postImages: mutate, ...rest}; + return {postImages: mutateAsync, ...rest}; }; export default useRequestPostImages; diff --git a/client/src/hooks/useAddImagesPage.ts b/client/src/hooks/useAddImagesPage.ts index 0bd45f490..917a109a3 100644 --- a/client/src/hooks/useAddImagesPage.ts +++ b/client/src/hooks/useAddImagesPage.ts @@ -16,7 +16,7 @@ const useAddImagesPage = () => { const [images, setImages] = useState>([]); const [isPrevImageDeleted, setIsPrevImageDeleted] = useState(false); const addedImages = images.filter(image => image instanceof File); - const {images: prevImages} = useRequestGetImages(); + const {images: prevImages, isSuccess} = useRequestGetImages(); const urls = images.map(image => { if (image instanceof File) { return URL.createObjectURL(image); @@ -29,15 +29,22 @@ const useAddImagesPage = () => { const navigate = useNavigate(); const eventId = getEventIdByUrl(); - const {postImages, isPending, isSuccess: isSuccessPostImage} = useRequestPostImages(); + const {postImages, isPending} = useRequestPostImages(); const {deleteImage} = useRequestDeleteImage(); useEffect(() => { - if (!prevImages) return; + if (!isSuccess) return; setImages([...prevImages]); - }, [prevImages]); + }, [prevImages, isSuccess]); + + useEffect(() => { + console.log(images); + }, [images]); const handleChangeImages = (event: React.ChangeEvent) => { + //TODO: (@Todari): 현재 A 이미지 추가 -> A 이미지 x 버튼 눌러 취소 -> 다시 A 이미지 추가 시 업로드 되지 않음 + // event.target.files가 변경되지 않기 때문에 onChange에 넣은 + // handleChangeImages가 실행되지 않아 일어나는 문제로 추정 if (event.target.files) { const dataTransfer = new DataTransfer(); @@ -57,24 +64,26 @@ const useAddImagesPage = () => { deleteImage({ imageId: images[index].id, }); - setIsPrevImageDeleted(false); + setIsPrevImageDeleted(true); } else { setImages(prev => prev.filter((_, idx) => idx !== index)); } }; - const canSubmit = !!addedImages || isPrevImageDeleted; + const canSubmit = addedImages.length !== 0 || isPrevImageDeleted; - const submitImages = () => { - const formData = new FormData(); + const submitImages = async () => { + if (addedImages.length !== 0) { + const formData = new FormData(); - if (!addedImages) return; + for (let i = 0; i < addedImages.length; i++) { + formData.append('images', addedImages[i], addedImages[i].name); + } - for (let i = 0; i < addedImages.length; i++) { - formData.append('images', addedImages[i], addedImages[i].name); + await postImages({formData}); } - postImages({formData}); + navigate(`/event/${eventId}/admin`); }; useEffect(() => { @@ -85,11 +94,6 @@ const useAddImagesPage = () => { }; }, []); - useEffect(() => { - if (!isSuccessPostImage) return; - navigate(`/event/${eventId}/admin`); - }, [isSuccessPostImage]); - return {fileInputRef, handleChangeImages, urls, handleDeleteImage, isPending, canSubmit, submitImages}; };