나의 개발일지

[React/TypeScript] 최종프로젝트 - Mango(환경오염 줄이기 / 지구 살리기 프로젝트!) (진행 중) - 로그인 에러메세지 수정 (useEffect / custom Hook) 본문

과제 및 팀프로젝트

[React/TypeScript] 최종프로젝트 - Mango(환경오염 줄이기 / 지구 살리기 프로젝트!) (진행 중) - 로그인 에러메세지 수정 (useEffect / custom Hook)

heew0n 2024. 1. 23. 20:57

 

 

로그인 시 이메일 또는 비밀번호가 틀릴 시 custom hook을 만들어 에러메세지를 modal창으로 띄워주려고 했다.

import { useCallback, useState } from 'react';

const usePrintError = (error: any): [string, (error: any) => void] => {
  const [errMsg, setErrMsg] = useState(error);

  const printErr = useCallback((error: any) => {
    switch (error.code) {
      case 'auth/user-not-found':
        return setErrMsg('이메일이 일치하지 않습니다.');
      case 'auth/wrong-password':
        return setErrMsg('비밀번호가 일치하지 않습니다.');
      case 'auth/email-already-in-use':
        return setErrMsg('이미 사용 중인 이메일입니다.');
      case 'auth/invalid-email':
        return setErrMsg('유효하지 않은 이메일 입니다.');
      case 'auth/too-many-requests':
        return setErrMsg('너무 많은 요청을 보냈습니다. 잠시 후 다시 시도하세요.');
      case 'auth/internal-error':
        return setErrMsg('잘못된 요청입니다.');
      case 'auth/invalid-credential':
        return setErrMsg('이메일 또는 비밀번호가 일치하지 않습니다');
      case 'auth/network-request-failed':
        return setErrMsg('네트워크 연결에 실패 하였습니다.');
      case 'auth/email-already-exists':
        return setErrMsg('제공된 이메일을 기존 사용자가 이미 사용 중입니다.');
      default:
        console.log('New Error code:', error.code);
        setErrMsg(error.code);
    }
  }, []);
  return [errMsg, printErr];
};

export default usePrintError;


export default usePrintError;

 

 

 

 

이메일 및 비밀번호가 틀렸을 때, 에러 메세지가 뜨긴 뜨는데 메세지 내용이 빈값으로 뜬다

그리고 나서 한 번 더 시도하면 그제서야 제대로 된 에러 메세지가 뜨게 된다.

const [errorMsg, setErrorMsg] = usePrintError('');

 

처음엔 바보같이 초기값이 빈 값이라 그런가 해서 이것저것 넣어보다가 소용이 없어서

차근차근 다시 살펴보았다.

 

 

 

 

 

문제의 코드

  // 로그인
  const signIn: SubmitHandler<Data> = async (data) => {
    try {
      const userCredential = await signInWithEmailAndPassword(auth, data.email, data.password);
      console.log('userCredential', userCredential);

      // 로그인 성공 시 role, authCurrentUser의 recoil(전역상태) update
      const user = userList && userList.find((user) => user.uid === authCurrentUser?.uid);
      if (user && auth) {
        setRole(user.role);
      }
      // home으로 이동
      navigate('/');
    } catch (error) {
      setErrorMsg(error);

      const onClickSave = () => {
        modal.close();
      };

      const openModalParams: Parameters<typeof modal.open>[0] = {
        title: '[로그인 오류]',
        message: errorMsg,
        leftButtonLabel: '',
        onClickLeftButton: undefined,
        rightButtonLabel: '확인',
        onClickRightButton: onClickSave
      };
      modal.open(openModalParams);
      //alert(errorMsg);
    }
  };

 

 

문제는 setErrorMsg 함수가 비동기적으로 동작하고 있기 때문에,

setErrorMsg  함수를 호출한 직후에 errorMsg의 값이 바로 업데이트되지 않았다.

따라서 setErrorMsg를 호출한 후에 바로 errorMsg를 사용하면 여전히 이전의 값을 가지고 있는다.

이를 해결하기 위해 setErrorMsg 를 호출하고 나서 모달을 열어주는 로직을 setErrorMsg 가 완전히 완료된 후에도 실행

되도록 변경했다. useEffect를 사용하여 errorMsg가 실행된 후 모달이 열리도록 해서 항상 값이 나올 수 있게 되었다 

 

 

 

수정코드

 useEffect(() => {
    if (errorMsg) {
      const onClickSave = () => {
        modal.close();
      };

      const openModalParams: Parameters<typeof modal.open>[0] = {
        title: '[로그인 오류]',
        message: errorMsg,
        leftButtonLabel: '',
        onClickLeftButton: undefined,
        rightButtonLabel: '확인',
        onClickRightButton: onClickSave
      };
      modal.open(openModalParams);
    }
  }, [errorMsg]);

  // 로그인
  const signIn: SubmitHandler<Data> = async (data) => {
    try {
      const userCredential = await signInWithEmailAndPassword(auth, data.email, data.password);
      console.log('userCredential', userCredential);

      // 로그인 성공 시 role, authCurrentUser의 recoil(전역상태) update
      const user = userList && userList.find((user) => user.uid === authCurrentUser?.uid);
      if (user && auth) {
        setRole(user.role);
      }
      // home으로 이동
      navigate('/');
    } catch (error) {
      setErrorMsg(error);
    }
  };

 

 

 

 

정상적으로 처음부터 에러메세지가 잘 보여진다!