[TIL] kakao 로그인 | React-Query | axios

Hi! I'm JENNIE·2022년 8월 30일
1

TIL : 기록

목록 보기
8/16
post-thumbnail

react-query 의 늪..

이번 프로젝트에서 react-query도 axios도 처음 써보는지라 뭐가 뭔지 모르겠..
소셜 로그인 간단할 줄 알았는데..... ㅎ ㅏ........ 일단 지금의 문제가

  1. useQuery를 여러번 써야함
  2. 1이 끝나면 2가 실행되어야 함 (동기적 실행)
  3. 다른 탭(창)에 갔다오면 useQuery가 자동으로 refetch를 해서 자꾸 에러 화면이 뜸
  4. isLoading, isError가 쿼리마다 있는데 어차피 같은 화면 띄울건데.. 한꺼번에 처리 못 할까?

먼저 최초의 코드부터 👩🏻‍💻

전 code

  /* Kakao Login */
  const [searchParams] = useSearchParams();
  const [isToken, setIsToken] = useState<boolean>(false);

  const AUTHORIZE_CODE = searchParams.get('code');

  const kakaoTokenLink = `https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id=${process.env.REACT_APP_REST_API_KEY}&redirect_uri=${process.env.REACT_APP_REDIRECT_URI}&code=${AUTHORIZE_CODE}`;

//1. 인가코드 보내서 토큰 받기(from Kakao)
  const getKakaoToken = async () => {
    return await axios.post(kakaoTokenLink, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    });
  };

//2. 토큰 보내서 사용자 정보 받기(from Backend)
  const getUserInfo = async () => {
    return await axios.post('/data/optionInfo.json', {
       kakaoToken: localStorage.getItem('kakaoToken'),
     });
  };

  const { data: kakaoToken,
		isLoading,
		isError, 
	} = useQuery('getKakaoToken', getKakaoToken, {
    onSuccess: kakao => {
      localStorage.setItem('kakaoToken', kakao.data.access_token);
      setIsToken(!isToken);
			getUserInfo();},
  });

  if (isLoading) {
    return <Loading>Loading. . .</Loading>;
  }
  if (isError) {
    return <Loading>Error ⚠️</Loading>;
  }
  • 동기적 실행을 위해 useQuery안에 두번째 실행할 함수(getUserInfo)를 넣어줌
  • getUserInfo 실행에 성공하면 유저 정보를 받아올 건데, 성공했을 때 이후 로직을 어떻게…? 어디에…?
  • 뭔가 아닌 것 같은 느낌 솔솔(많이)

중간 code

//1. 인가코드 보내서 토큰 받기(from Kakao)
const getKakaoToken = async () => {
    return await axios.post(kakaoTokenLink, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    });
  };

  const { data: kakaoToken } = useQuery('getKakaoToken', getKakaoToken, {
    onSuccess: kakao => {
      localStorage.setItem('kakaoToken', kakao.data.access_token);
      setIsToken(!isToken);
    },
  });

//2. 토큰 보내서 사용자 정보 받기(from Backend)
  const getUserInfo = async () => {
    return await axios.post('/data/optionInfo.json', {
       kakaoToken: localStorage.getItem('kakaoToken'),
     });
  };

  const { data: kakaoUserInfo } = useQuery('getUserInfo', getUserInfo, {
    enabled: !!kakaoToken,// kakaoToken이 있으면 실행
  });
  • useQuery 각각 분리하고, enabled 옵션을 이용했다
  • enabled 옵션을 이용하면 useQuery를 동기적으로 사용 가능하다
  • enabled == true 일 때 해당 useQuery를 실행함
    • 내 코드에서는 인가코드를 보내 kakaoToken을 가져오면 getUserInfo 함수를 실행하기 위해 enabled: !!kakaoToken 을 넣어줌
  • 남은 문제?
    • 다른 창에 갔다 오면 useQuery가 자동으로 refetch를 한다
      • kakao에 보내는 토큰 요청은 최초 1회만 실행 되어야 함!
      • 아니면 에러난다.
    • isLoading, isError도 처리를 해주고 싶다… 한번에..!

최종 code

//1. 인가코드 보내서 토큰 받기(from Kakao)
  const getKakaoToken = async () => {
    return await axios.post(kakaoTokenLink, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      maxRedirects: 0,
    });
  };

  const {
    data: kakaoToken,
    isLoading: kakaoTokenIsLoding,✅
    isError: kakaoTokenIsError,} = useQuery('getKakaoToken', getKakaoToken, {
    onSuccess: kakao => {
      localStorage.setItem('kakaoToken', kakao.data.access_token);
    },
    refetchOnWindowFocus: false,});

//2. 토큰 보내서 사용자 정보 받기(from Backend)
  const getKakaoUserInfo = async () => {
    // return await axios.post('/data/optionInfo.json', {
    //   kakaoToken: localStorage.getItem('kakaoToken'),
    // });
    return await axios.get('/data/optionInfo.json');
  };

  const {
    data: kakaoUserInfo,
    isLoading: kakaoUserInfoIsLoding,✅
    isError: kakaoUserInfoIsError,} = useQuery('getKakaoUserInfo', getKakaoUserInfo, {
    enabled: !!kakaoToken,
    refetchOnWindowFocus: false,});

  useEffect(() => {
    getKakaoToken();
    getKakaoUserInfo();
  }, []);

  //로딩 시 ✅
  if (kakaoTokenIsLoding || kakaoUserInfoIsLoding) {
    return <Loading />;
  }
  //에러 시 ✅
  if (kakaoTokenIsError || kakaoUserInfoIsError) {
    return <Error />;
  }
  • useEffect 안에 getKakaoToken(); 함수와 getKakaoUserInfo(); 함수를 넣어주어 처음 렌더링 시에 두 함수가 실행되도록 한다
  • 자동 refetch를 막아주기 위해, refetchOnWindowFocus 옵션을 false 로 설정에러 안난다 이제 ㅍ0ㅍ
  • 두 함수가 실행 될 때 Loading, Error 화면은 어차피 같으므로, 한번에 처리해 주기 위해 각각의 isLoading, isError에 다른 이름을 부여하여 논리 연산자 ||(OR) 를 이용하였다
  • useQuery를 구조분해할당 안 하고 전체를 정의한 다음에 .data, .isLoading, .isError로 접근해서 사용해도 되지만 이 방법이 더 깔끔한 듯 함!
  • useQuery가 여러개 일 때 사용할 수 있는 useQueries도 있던데 그건 나중에 더 알아보자…!
profile
Front-End Developer

0개의 댓글