[프로젝트] 회원정보 조회 및 수정 시 리액트 쿼리 사용하기 !

2024. 6. 11. 18:50· 프로젝트
목차
  1. 왜 리액트 쿼리를 사용했는가 ? 
  2. 리액트 쿼리 적용 후 MainLayout.tsx
  3. 기존 ProfileEditModal.tsx 
  4. 리액트 쿼리 적용 후  ProfileEditModal.tsx 
  5. 완성 결과 

지난 포스트에서는 리액트 쿼리에 대해 작성해보았고 오늘은 실제로 진행중인 프로젝트에 적용한 내용에 대해 작성할 것이다 ! 

 

왜 리액트 쿼리를 사용했는가 ? 

현재 메인 화면에 진입했을 때 MainLayout.tsx 에 존재하는 네비게이션 바에서 회원 정보를 넘겨주어 네비게이션 바에서 회원 정보를 렌더링 하는 형식으로 코드를 작성했었다. 

 

회원 정보가 담긴 네비게이션 바

 

리액트 쿼리 적용 전 회원 조회 코드  MainLayout.tsx

const { data, callApi, statusCode } = useApi();
  useEffect(() => {
    const fetchData = async () => {
      const token = localStorage.getItem("accessToken");
      const headers = token ? { Authorization: `Bearer ${token}` } : {};
      if (token) {
        await callApi("/api/members/me", "get", {
          headers,
        });
      }
    };
    fetchData();
  }, []);
  if (data) {
    console.log(data);

( useApi는 api 호출을 위해 만들어놓은 커스텀 훅이고 MainLayout.tsx 폴더에서 위와 같이 useEffect 를 사용하여 회원 정보를 조회 했었다. )

하지만 회원 정보 수정 및 이미지 추가, 삭제를 구현하게 되면서 회원 정보 수정을 모달로 구현하게 되었는데 정보를 수정했는데 뒤에 있는 모달에 뜬 정보를 변경할수가 없었다. 왜냐하면 현재 회원 조회는 MainLayout 컴포넌트가 렌더링 되었을 때 회원 정보를 조회하게 구현되어 있는데 모달창에서 회원 정보의 변경이 발생하기 때문에 변경된 회원정보를 보기 위해선 다시 컴포넌트를 렌더링 해야하는 상황이 발생했다.. ! (새로고침을 하던지 .. ) 

회원 정보 모달

 

따라서 리액트 쿼리를 사용하면 서버에 있는 데이터를 최신화 할 수 있으니 모달창을 띄워둔채로 회원 정보 데이터가 변경되게 리액트 쿼리를 사용해 리팩토링을 진행하였다. (useMutation을 사용해 변경시 다시 조회하도록 ..! )

 

리액트 쿼리 적용 후 MainLayout.tsx

const { isLoading, isError, data } = useMemberInfoQuery();

 

useMemberInfoQuery.ts

// 유저 관련 데이터 get 요청 쿼리를 저장
import { useQuery } from "@tanstack/react-query";
import client from "../../../config/axios";

const fetchMemberInfo = async () => {
  const token = localStorage.getItem("accessToken");
  const headers = token ? { Authorization: `Bearer ${token}` } : {};
  const response = await client.get("/api/members/me", { headers });
  return response.data.data;
};

export const useMemberInfoQuery = () => {
  const { isLoading, isError, data, error } = useQuery({
    queryKey: ["memberInfo"],
    queryFn: fetchMemberInfo,
  });

  return { isLoading, isError, data, error };
};

 

useQuery를 사용해 queryKey 값으로 memberInfo 로 설정해주고 queryFn으로 회원정보를 get 하는 비동기 api 함수를 호출해주었다. 또한 MainLayout에서는 한줄로 선언해주는 것만으로 회원 정보 조회를 할 수 있었다 !! 

 

기존 ProfileEditModal.tsx 

모달 창 내에 직접 api 호출 함수를 작성했었다. 

  const handleImageUpload = () => {
    if (!selectedImage) {
      alert("이미지를 먼저 선택해주세요");
      return;
    }
    const formData = new FormData();
    formData.append("image", selectedImage);

    callApi("/api/members/me/profile-image", "put", formData, {
      "Content-Type": "text/plain",
      Authorization: `Bearer ${token}`,
    })
      .then(response => {
        console.log(response);
        alert("프로필 사진이 설정되었습니다.");
      })
      .catch(error => {
        console.log(error);
      });
  };

  const handleImageDelete = () => {
    callApi("/api/members/me/profile-image", "delete", { headers })
      .then(() => {
        alert("기본이미지로 설정되었습니다.");
        setSelectedImage(null);
        setPreviewImage(null);
      })
      .catch(error => {
        console.log(error);
      });
  };

  const handleNicknameChange = () => {
    callApi("/api/members/me", "put", { nickname: nickname }, headers)
      .then(() => {
        setErrorMessage(data);
      })
      .catch(error => {
        console.log(error);
      });
  };

 

 

리액트 쿼리 적용 후  ProfileEditModal.tsx 

const { uploadProfileImage, deleteProfileImage, updateNickname } =
    useProfileMutations();
  const handleImageUpload = () => {
    if (!selectedImage) {
      alert("이미지를 먼저 선택해주세요");
      return;
    }
    const formData = new FormData();
    formData.append("image", selectedImage);

    uploadProfileImage.mutate(formData); // 변경
  };

  const handleImageDelete = () => {
    deleteProfileImage.mutate(); // 변경
  };

  const handleNicknameChange = () => {
    updateNickname.mutate({ newNickname: nickname }); // 변경
  };

 

 

useProfileMutations.ts

import { useMutation, useQueryClient } from "@tanstack/react-query";
import client from "../../../config/axios";

const token = localStorage.getItem("accessToken");

export const useProfileMutations = () => {
  const queryClient = useQueryClient();

  const uploadProfileImage = useMutation({
    mutationFn: (formData: FormData) =>
      client.put("/api/members/me/profile-image", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
          Authorization: `Bearer ${token}`,
        },
      }),
    onSuccess: () => {
      console.log("프로필 사진 업로드 성공");
      queryClient.invalidateQueries({ queryKey: ["memberInfo"] });
    },
    onError: error => {
      console.error("프로필 사진 업로드 실패:", error);
    },
  });

  const deleteProfileImage = useMutation({
    mutationFn: () =>
      client.delete("/api/members/me/profile-image", {
        headers: {
          "Content-Type": "multipart/form-data",
          Authorization: `Bearer ${token}`,
        },
      }),
    onSuccess: () => {
      console.log("프로필 사진 삭제 성공");
      queryClient.invalidateQueries({ queryKey: ["memberInfo"] });
    },
    onError: error => {
      console.error("프로필 사진 삭제 실패:", error);
    },
  });

  const updateNickname = useMutation({
    mutationFn: ({ newNickname }: { newNickname: string }) =>
      client.put(
        "/api/members/me",
        { nickname: newNickname },
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        },
      ),
    onSuccess: () => {
      console.log("닉네임 변경 성공");
      queryClient.invalidateQueries({ queryKey: ["memberInfo"] });
    },
    onError: error => {
      console.error("닉네임 변경 실패:", error);
    },
  });

  return {
    uploadProfileImage,
    deleteProfileImage,
    updateNickname,
  };
};

export default useProfileMutations;

useMutation을 사용해 옵션으로 onSuccess시 queryClient.invalidateQueries를 실행해 queryKey 의 유효성을 제거해주고 서버로 부터 새 데이터를 조회해 올 수 있도록 코드를 작성했다!! 

 

완성 결과 

변경사항이 네비게이션 바에 바로바로 적용된다!

 

 

'프로젝트' 카테고리의 다른 글

[프로젝트] SingK 를 마치고 쓰는 회고  (0) 2024.09.19
useQuery 사용 시 Error: No QueryClient set, use QueryClientProvider to set one 에러 해결  (1) 2024.06.11
[프로젝트] SingK 프로젝트 돌입 !  (0) 2024.05.04
[프로젝트] 구르미월드 개발을 마치고 쓰는 회고 👩🏻‍💻  (1) 2024.03.02
[프로젝트] '구르미 월드' 프로젝트 돌입 !  (1) 2023.12.20
  1. 왜 리액트 쿼리를 사용했는가 ? 
  2. 리액트 쿼리 적용 후 MainLayout.tsx
  3. 기존 ProfileEditModal.tsx 
  4. 리액트 쿼리 적용 후  ProfileEditModal.tsx 
  5. 완성 결과 
'프로젝트' 카테고리의 다른 글
  • [프로젝트] SingK 를 마치고 쓰는 회고
  • useQuery 사용 시 Error: No QueryClient set, use QueryClientProvider to set one 에러 해결
  • [프로젝트] SingK 프로젝트 돌입 !
  • [프로젝트] 구르미월드 개발을 마치고 쓰는 회고 👩🏻‍💻
배트리버
배트리버
🐾 사람 좋아, 개발 좋아 🐾 궁금한 건 끝까지 파고들고, 배운 건 즐겁게 나누는 개발자의 놀이터
배트리버
리트리버의 개발 놀이터
배트리버
전체
오늘
어제
  • 분류 전체보기
    • 네트워크
    • 기초 셋팅
    • 오늘의 일기
    • 리액트
    • 코테 준비
      • 프로그래머스
      • 백준
    • 코드스테이츠44기 프론트엔드
    • HTML-CSS-JavaScript
      • HTML
      • CSS
      • JavaScript
    • 자료구조&알고리즘
    • TypeScript
    • Git
    • Tip
    • 프로젝트
    • Next.js
    • 트러블슈팅

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 리액트쿼리
  • 코드스테이츠 프론트엔드
  • 자바스크립트
  • 코드스테이츠 블로깅
  • 프로젝트 회고
  • 타입스크립트문법
  • BFS
  • 오블완
  • KPT 회고
  • 코드스테이츠 회고록
  • 코드스테이츠 44기
  • 티스토리챌린지
  • 프로그래머스
  • 탄스택쿼리
  • 코드스테이츠
  • 코드스테이츠 44기 프론트엔드
  • 네트워크
  • 리액트 상태관리
  • 리액트
  • 자바스크립트 비동기

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
배트리버
[프로젝트] 회원정보 조회 및 수정 시 리액트 쿼리 사용하기 !
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.