Skip to content

Commit

Permalink
fix: 사진 추가한 후 다시 접속 시 반영이 되지 않는 버그 (#727)
Browse files Browse the repository at this point in the history
* fix: post를 기다린 후 navigate시켜서 캐시 데이터가 remove 됨을 보장받도록 변경

* feat: 잘못 설정된 canSubmit, setIsPrevImageDeleted 변경

* feat: body 타입이 FormData인 경우 header를 삽입하지 않도록 함

* feat: images POST 요청을 requestPostWithoutResponse 함수를 이용하도록 함

* fix: get 메소드가 오류날 때, 무한 렌더링이 일어나는 문제 수정

---------

Co-authored-by: 이태훈 <[email protected]>
Co-authored-by: pakxe <[email protected]>
  • Loading branch information
3 people authored Oct 10, 2024
1 parent 897af5b commit 9921db5
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 48 deletions.
31 changes: 23 additions & 8 deletions client/src/apis/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type RequestInitWithMethod = Omit<RequestInit, 'method'> & {method: Method};

type HeadersType = [string, string][] | Record<string, string> | Headers;

export type Body = BodyInit | object | null;
export type Body = BodyInit | object | null; //init안에 FormDATA있음.

type RequestProps = {
baseUrl?: string;
Expand All @@ -32,6 +32,12 @@ type RequestProps = {
method: Method;
};

type CreateRequestInitProps = {
body?: Body;
method: Method;
headers?: HeadersType;
};

type RequestMethodProps = Omit<RequestProps, 'method'>;

type FetchType = {
Expand Down Expand Up @@ -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<FetchType>) => {
Expand All @@ -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;
Expand Down
21 changes: 1 addition & 20 deletions client/src/apis/request/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,7 @@ export interface RequestPostImages {
}

export const requestPostImages = async ({eventId, formData}: WithEventId<RequestPostImages>) => {
// 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) => {
Expand Down
6 changes: 3 additions & 3 deletions client/src/hooks/queries/images/useRequestPostImages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
38 changes: 21 additions & 17 deletions client/src/hooks/useAddImagesPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const useAddImagesPage = () => {
const [images, setImages] = useState<Array<LoadedImage | AddedImage>>([]);
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);
Expand All @@ -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<HTMLInputElement>) => {
//TODO: (@Todari): 현재 A 이미지 추가 -> A 이미지 x 버튼 눌러 취소 -> 다시 A 이미지 추가 시 업로드 되지 않음
// event.target.files가 변경되지 않기 때문에 onChange에 넣은
// handleChangeImages가 실행되지 않아 일어나는 문제로 추정
if (event.target.files) {
const dataTransfer = new DataTransfer();

Expand All @@ -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(() => {
Expand All @@ -85,11 +94,6 @@ const useAddImagesPage = () => {
};
}, []);

useEffect(() => {
if (!isSuccessPostImage) return;
navigate(`/event/${eventId}/admin`);
}, [isSuccessPostImage]);

return {fileInputRef, handleChangeImages, urls, handleDeleteImage, isPending, canSubmit, submitImages};
};

Expand Down

0 comments on commit 9921db5

Please sign in to comment.