고통의 연속
회원정보 수정 기능을 구현하는데, 금방 될 줄 알았는데, 고려해야 할 게 많아서 생각보다 오래걸렸다ㅠ.ㅠ
supabase auth로 회원가입을 하면 Authentication에서 제공하는 정보를 담기 위해 users 라는 public 테이블에 자동으로 저장이 되는데 (트리거 함수를 통해 구현)
begin
insert into public.users(id, email, nickname, avatar_url)
values(new.id, new.email, new.raw_user_meta_data ->> 'nickname', new.raw_user_meta_data ->> 'avatar_url');
return new;
end;
닉네임 수정을 하면?
메타데이터도 수정을 해줘야 하고, public 테이블인 users 테이블도 수정을 해줘야 했다.
그래서 다음과 같이 함수를 작성하였다.
export const updateUser = async (userId: string, newNickname: string) => {
// 메타데이터 업데이트
const { data, error } = await supabase.auth.updateUser({
data: { nickname: newNickname },
});
// users 테이블 업데이트
const { error: usersError } = await supabase
.from('users')
.update({ nickname: newNickname })
.eq('id', userId);
};
수정을 하면 DB에 메타데이터도 잘 수정되고, users 테이블도 잘 수정이 되는데,
수정한 닉네임이 바로 반영이 안되고, 새로고침을 해야지만 반영되는 문제가 발생했다.
const {
data: user,
error,
isLoading,
refetch,
} = useQuery({
queryKey: ['user', userId],
queryFn: () => getUserDataById(userId),
enabled: userId !== undefined,
});
const queryClient = useQueryClient();
const { mutate } = useMutation({
mutationFn: () => updateUser(userId, newNickname), // ❌
onSuccess: async () => {
await queryClient.invalidateQueries([
'user',
userId,
] as InvalidateQueryFilters);
await refetch(); // 추가한 부분!
setIsEditing(false);
},
});
react-query로 가져온 데이터를 invalidateQueries로 무효화했는데도 수정된 값이 잘 반영이 안되었다. 그래서 고통을 받다가.. refetch를 통해 해결을 해 보았다.
알고 보니 mutate 함수를 호출하는 방법이 잘못되었었다.!
여러 개의 값을 넘겨주고 싶을 땐 객체 형식으로 묶어서 보내주는 것이었다.
수정한 방법은 다음과 같다.
const {
data: user,
error,
isLoading,
} = useQuery({
queryKey: ['user', userId],
queryFn: () => getUserDataById(userId),
enabled: userId !== undefined,
});
const queryClient = useQueryClient();
const { mutate } = useMutation({
mutationFn: updateUser,
onSuccess: async () => {
await queryClient.invalidateQueries([
'user',
userId,
] as InvalidateQueryFilters);
},
});
const onEditDone = async () => {
// avatar 수정이 있을 때
if (newAvatar) {
// storage 업로드
const { data: fileData, error: fileError } = await supabase.storage
.from('avatars')
.upload(`${Date.now()}`, newAvatar);
if (fileError) {
console.error('이미지 업로드 에러', fileError.message);
return;
}
const { data: imageData } = supabase.storage
.from('avatars')
.getPublicUrl(fileData.path);
const newAvatarUrl = imageData.publicUrl;
mutate({ userId, newUsername, newAvatarUrl });
setIsEditing(false);
} else {
// 닉네임만 수정할 때
mutate({ userId, newUsername });
setIsEditing(false);
}
};