유저가 이미지를 업로드할 때 이미지가 서버에 전송되고 실제 화면에 표시되기까지 약간의 시간이 걸린다. 유저의 사용성 개선을 위해 이 대기 시간 동안 로딩페이지를 보여주려고 한다.
// MyPage.jsx
const imageSubmitHandler = async (e) => {
const file = e.target.files[0];
if (file) {
const formData = new FormData();
formData.append('profileUrl', file);
try {
const responseData = await updateMyPageProfileImage(formData);
if (responseData) {
setProfileImage(responseData);
setProfileModal(false);
} else {
alert('프로필 이미지 등록에 실패했습니다. 잠시 후 다시 시도해주세요.');
}
} catch (error) {
alert('프로필 이미지 등록에 실패했습니다. 잠시 후 다시 시도해주세요.');
console.error(error);
}
}
};
여기에서 useMutation
훅을 사용하여 isLoading
이 true
인 동안 로딩페이지를 보여주는 방식으로 수정을 해보자!
먼저 로딩스피너 컴포넌트를 만들었다.
// LoadingSpinner.jsx
import React from 'react';
import './LoadingSpinner.css';
const LoadingSpinner = () => {
return (
<div className='loading-container'>
.
.
.
</div>
);
};
export default LoadingSpinner;
// MyPage.jsx
import { useMutation } from 'react-query';
const mutation = useMutation(updateMyPageProfileImage);
const imageSubmitHandler = async (e) => {
const file = e.target.files[0];
if (file) {
const formData = new FormData();
formData.append('profileUrl', file);
try {
const responseData = await mutation.mutateAsync(formData);
if (responseData) {
setProfileImage(responseData);
setProfileModal(false);
} else {
alert('프로필 이미지 등록에 실패했습니다. 잠시 후 다시 시도해주세요.');
}
} catch (error) {
alert('프로필 이미지 등록에 실패했습니다. 잠시 후 다시 시도해주세요.');
console.error(error);
}
}
};
.
.
.
{mutation.isLoading ? <LoadingSpinner isLoading={mutation.isLoading} /> : null}
로딩 및 에러 상태를 자동으로 관리해주는 react-query의 useMutation을 사용하였으나, useMutation의 주요 기능 중 하나인 로딩 및 에러 상태관리 기능을 코드에서 활용을 못하고 있다.
// LoadingSpinner.jsx
import PropTypes from 'prop-types';
const LoadingSpinner = ({ isLoading }) => {
if (!isLoading) return null;
return (
<div className='loading-container'>
.
.
.
LoadingSpinner.propTypes = {
isLoading: PropTypes.bool.isRequired,
};
// MyPage.jsx
const mutation = useMutation(updateMyPageProfileImage);
const imageSubmitHandler = async (e) => {
const file = e.target.files[0];
if (file) {
const formData = new FormData();
formData.append('profileUrl', file);
mutation.mutate(formData, {
onSuccess: (data) => {
setProfileImage(data);
setProfileModal(false);
},
onError: (error) => {
alert('프로필 이미지 등록에 실패했습니다. 잠시 후 다시 시도해주세요.');
console.error(error);
}
});
}
};
.
.
.
{mutation.isLoading && <LoadingSpinner />}
async/await
을 사용하여 API호출 후의 응답을 직접 확인하여 그 결과를 처리하였으나, mutation.mutate
의 콜백 옵션을 사용하여 결과를 처리하는 방법으로 개선했다.onError
콜백을 사용하여 중복을 제거하였다.useMutation
훅을 사용하면서 try-catch
구문이 필요없어져 코드가 간결해졌다.mutation.isLoading
을 사용하여 로딩 상태를 관리할 수 있게 되었다.// LoadingSpinner.jsx
const LoadingSpinner = () => {
return (
<div className='loading-container'>
.
.
.