React Query(TanStack Query)에서 서버에 create, update, delete 요청을 보내야 하는 경우 useMutation
을 이용한다.
프로젝트 진행중 이미지를 서버로 업로드하기 위해 formdata를 전송해야 하는 상황이었다. 서버에서는 이미지를 받아서 S3에 저장 후 url을 응답으로 보내준다.
우선 headers에 'Content-Type': 'multipart/form-data'
를 설정해주어야 한다. Content-Type은 HTTP 요청에서 Message Body에 들어가는 데이터의 타입을 명시해주는 필드이다.
const config = {
headers: { 'Content-Type': 'multipart/form-data' },
};
요청 코드를 단순화 하기 위해 우선 config이라는 변수로 따로 선언을 해 주었다.
그리고 axios를 이용해 서버로 formdata를 전송해주는 훅을 만들었다.
const useGetPhotoUrl = () => {
return useMutation(
(formData: FormData): Promise<AxiosResponse> =>
axiosInstance.post(`/upload`, formData, config),
);
};
서버 URL을 포함하여 별도로 생성해둔 axiosInstance에 post 요청으로 endpoint와 formdata, 위에 적어둔 config을 포함시킨다.
초반에 formdata를 body data로 포함시켜야한다고 생각해서 data: formData로 작성했더니 계속 파일이 요청에 포함되지 않아서 고생했던 기억이 난다..
사진을 첨부하는 컴포넌트에서 이제 작성한 훅을 사용만 하면 된다.
const { mutate } = useGetPhotoUrl();
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { files } = e.target;
const formData = new FormData();
if (files) {
const fileRef = files[0];
resizeImageToBlob(fileRef).then((blob: Blob) => {
formData.append('img', blob);
mutate(formData, {
onSuccess: res =>
dispatch(updateRentalInfo({ key: 'imageUrl', value: res.data })),
});
});
}
};
이미지가 input에 업로드 되었을 때 실행되는 handleChange 함수이다.
resizeImageToBlob
이라는 함수를 먼저 수행하여 이미지의 용량을 줄여주고 생성한 FormData에 추가(append)해준다.
useGetPhotoUrl
훅에서 구조분해할당으로 가져온 mutate 함수에 최종적으로 이미지가 담긴 formdata를 전달해주면 서버로 이미지가 잘 전송이 된다.