export const useSaveProfile = () => {
const navigate = useNavigate();
const { fetchUser } = useAuthStore();
return useMutation({
mutationFn: saveProfile,
onSuccess: (data) => {
fetchUser(data);
navigate('/profile/success');
},
onError: (error) => {
alert('프로필 저장에 실패했습니다. 다시 시도해주세요.');
console.error(error);
},
});
};
export const useEditProfile = (profile) => {
const { fetchUser } = useAuthStore();
return useMutation({
mutationFn: modifyProfile,
onSuccess: () => {
fetchUser(profile);
},
onError: (error) => {
console.error(error);
},
});
};
export const useFetchProfile = () => {
const { fetchUser } = useAuthStore();
const { data, isLoading, isError, error } = useQuery({
queryKey: ['profile'],
queryFn: getProfile,
staleTime: 600000,
onSuccess: (data) => {
fetchUser(data);
},
});
return { data, isLoading, isError, error };
};
Axios와 React-query를 사용하며 정상적으로 처리됐을 경우 response.data의 값을 user에 할당하도록 하였다.
useFetchProfile에서 onSuccess에 받아온 데이터를 바로 user에 할당되도록 설정했다.
내가 담당한 페이지는 ProfileSettingPage, ProfileEditPage이다. 처음 로그인을 했을 때 백엔드에서 ProfileSettingPage로 리다이렉트 시켜준다. 쿠키에 토큰을 담아서 통신하는 방식이므로 로그인 여부 확인을 위해 GET 요청을 하도록 설정했었다. 해당 요청에 대해서 백엔드는 data의 각 name, email 등의 필드에 null을 할당해서 반환해주었다.
ProfileEditPage에도 GET 요청을 넣어 최신 데이터를 보여주도록 했는데 여기서 문제가 생겼다.
전반적인 문제 과정은 아래와 같다.
위의 과정을 지나오면 ProfileEditPage에 내가 저장했던 profile 내용이 아니라 모든 필드에 null이 들어가 정보가 없다고 뜬다. onSuccess에 fetchUser(data)를 넣어버려서 요청에 대한 응답이 와도 모든 필드가 null이었던 user 상태가 업데이트 될 일이 없다. 게다가 ProfileSettingPage에 방문하고 10분 이내에 ProfileEditPage에 방문하게 되면 요청 자체가 안 날라간다.
isSuccess를 넣어서 무한 요청을 보내다가 다운되는 등의 여러 시행착오를 겪었고 다른 블로그를 참고하여 해결했다.
onSuccess의 내용을 없애 버리고 ProfileEditPage에 useEffect를 추가해주었다.
...
const { fetchUser } = useAuthStore();
const { data, isLoading, isError, error } = useFetchProfile();
const { canSave, emailError, profile, handleProfileFieldChange } = useProfile();
useEffect(() => {
if (data) {
fetchUser(data);
}
}, [data]);
...
//참고로 profile도 useEffect를 써서 user가 변경될 때마다 user 정보를 끌어오도록 했다.
미처 예상하지 못한 부분이라 원인을 찾고 해결하느라 오랜 시간이 걸렸다.
추가로 알고 있으면 좋을 것 같은 내용은 useQuery로 캐시된 데이터를 불러올 수 있다는 것이다.
구버전 기준으로 useQuery는 data를 받아올 때 데이터를 새로 받아와야 onSuccess가 실행된다.
요청에 대한 응답이 변하지 않으면 React Query가 내부적으로 상태를 변경하지 않아onSuccess
를 실행하지 않을 수 있다.
더하여 기타 설정이 없을 경우 useQuery는 staleTime 동안 캐시된 데이터를 사용한다. 따라서 staleTime 동안은 데이터를 새로 받아오지 않고, 요청을 보내지도 않고, onSuccess가 호출되지 않는다.
나중에 리액트 쿼리 공식 문서에서 최신 버전의 useQuery 는 onSuccess와 onError 처리를 제공하지 않는 것을 확인했다.. 공식 문서를 꼭 읽자 근데 너무 길어