yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-5] 페이지 전환 시 상태 값 보존 방법과 TypeScript 오류 #262

Closed CALKO9611 closed 1 year ago

CALKO9611 commented 1 year ago

질문 작성자

김대웅

문제 상황

[질문 1]

242 답변 해주신 내용처럼 코드를 수정하였으나 문제가 발생했습니다.

저희 조 같은 경우는 auth.currentUser에 담겨있는 phoneNumber는 읽기 전용이고, address라는 항목은 없기에 Firestore에 저장하고 그 값을 불러오는 방식을 취했습니다. image

하지만 이렇게 값을 설정하니 페이지를 새로고침을 하면 값이 불러 와지는데 단순히 다른 페이지로 이동 후 다시 마이페이지로 돌아오면 값이 비어있습니다. 아마도 debounce 사용을 위해 defaultValue로 값을 설정해서 그런 것 같은데.. 해결 방법이 궁금합니다! MyPage 이슈

firebase에 저장된 이메일 계정 ID : kitty@naver.com PW : a12345678

[질문 2] 부족하긴 하나 인터넷 검색을 통해 카카오 로그인을 구현을 했습니다.

import { LoginResponse, UserProfile } from 'kakao-sdk';

이와 같은 코드를 작성했는데 kakao-sdk -> 이 부분에서 빨간 줄이 뜨면서 '모듈을 찾을 수 없다!' 라고 알려줬지만 기능은 정상 작동 됩니다! 그대로 사용해도 괜찮은 건지 궁금합니다!

오류 전체 내용 ButtonKakao 이슈

LoginResponse, UserProfile 사용한 위치 image

프로젝트 저장소 URL

https://github.com/React-Project-lab5/React-Project-lab5 develop 브랜치

환경 정보

yamoo9 commented 1 year ago

답변 1. 페이지 전환 간, 상태 유지 방법

MyPage 컴포넌트 코드를 아래와 같이 수정해보세요. (주석 참고)

export default function MyPage() {
  // ...

 useEffect(() => {
    // 사용자 정보, 전화번호 또는 주소가 존재할 경우, 로딩 상태 false로 설정
    if (user && (phoneNumber || address)) {
      setIsLoading(false);
    }
  }, [address, phoneNumber, user]);

  useEffect(() => {
    const unsub = auth.onAuthStateChanged((user) => {
      if (user) {
        const getUserRef = doc(collection(db, 'users'), user.uid);
        getDoc(getUserRef).then((doc) => {
          if (doc.exists()) {
            const userData = doc.data();
            setName(userData.displayName);
            setEmail(userData.email);
            setPhoneNumber(userData.phoneNumber);
            setAddress(userData.address);
          } else {
            user.providerData.forEach((profile) => {
              setName(profile.displayName);
              setEmail(profile.email);
            });
            // Firestore 문서 정보가 없다면?
            // 로딩 상태 false로 설정
            setIsLoading(false);
          }
        });
      }
    });
    return unsub;
  }, []);

  // ...
}

구현 결과는 아래 영상과 같이 페이지 전환 시에도 상태(전화번호, 주소)는 유지됩니다. 😊

답변 2. TypeScript 타입 오류

kakao-sdk 패키지는 LoginResponse, UserProfile 타입을 제공하지 않습니다. 그러니 모듈을 찾을 수 없죠. 해당 타입은 react-kakao-login가 제공하지만, 개발자가 타입을 외부로 내보내지 않아서 꺼내와 사용할 수 없습니다. 😥

LoginResponse, UserProfile 타입은 react-kakao-login/src/types.ts 파일에 정의되어 있습니다.

interface LoginResponse {
  /** 토큰 타입, bearer 로 고정 */
  token_type: string;
  /** 사용자 액세스 토큰 값 */
  access_token: string;
  /** 액세스 토큰 만료 시간(초) */
  expires_in: string;
  /** 사용자 리프레시 토큰 값 */
  refresh_token: string;
  /** 리프레시 토큰 만료 시간(초) */
  refresh_token_expires_in: number;
  /** 인증된 사용자의 정보 조회 권한 범위 */
  scope: string; // 범위가 여러 개일 경우, 공백으로 구분
}

interface UserProfile {
  /** 회원번호 */
  id: number;
  /** 카카오계정 정보 */
  kakao_account: KakaoAccount;
  /** 카카오싱크 간편가입을 통해 로그인한 시각, UTC */
  synched_at: string;
  /** 서비스에 연결 완료된 시각, UTC */
  connected_at: string;
  /** JSON 추가 정보 */
  properties: Profile;
}

문제 해결을 위해 필요한 타입을 프로젝트 글로벌 타입 정의 파일에 추가합니다.

global.d.ts

interface LoginResponse {
  token_type: string;
  access_token: string;
  expires_in: string;
  refresh_token: string;
  refresh_token_expires_in: number;
  scope: string;
}

interface Profile {
  nickname: string;
  profile_image: string;
  thumbnail_image_url: string;
  profile_needs_agreement?: boolean;
}

interface KakaoAccount {
  profile: Profile;
  email: string;
  age_range: string;
  birthday: string;
  birthyear: string;
  gender: 'female' | 'male';
  phone_number: string;
  ci: string;
}

interface UserProfile {
  id: number;
  kakao_account: KakaoAccount;
  synched_at: string;
  connected_at: string;
  properties: Profile;
}

interface KakaoLoginResponse {
  response: LoginResponse;
  profile?: UserProfile;
}

KakaoLoginResponse을 글로벌 타입으로 정의했기 때문에 더 이상 TypeScript는 오류를 표시하지 않습니다. 😃