👀 깃허브 링크
😎 클론 사이트 바로가기
이슈가 있었던 부분은 제목 옆에 ❗를 붙였습니다.
- 회원가입/로그인
- 토글 버튼으로 회원가입/로그인을 따로 노출
- 일반 이메일 형식이 아닌 구글, 깃허브 아이디로도 가입 가능
- 사이트에 들어왔을 때 유저의 상태 변화 추적 가능
- 로그인, 로그아웃, 어플리케이션 초기화(새로고침 or 재시작) 시 변화 추적
- 구글, 깃허브가 아닌 일반 이메일 형식으로 회원가입/로그인 할 때 발생하는 에러 문구를
includes
와replace
메소드를 이용하여 표기
// 코드 생략
const [newAccount, setNewAccount] = useState(true);
const toggleAccount = () => setNewAccount(!newAccount);
{newAccount ? (
<div className={styled.auth__notice}>
<span>계정이 없으신가요?</span>
<div>
<span onClick={toggleAccount} className={styled.authSwitch}>
가입
</span>
<span>하기</span>
</div>
</div>
) : (
<div className={styled.auth__notice}>
<span>이미 Nwitter에 가입하셨나요?</span>
<div>
<span onClick={toggleAccount} className={styled.authSwitch}>
로그인
</span>
<span>하기</span>
</div>
</div>
)}
// 깃허브와 코드 같음
export const GoogleBtn = ({ newAccount }) => {
const dispatch = useDispatch();
const history = useHistory();
const onSocialClick = async (e) => {
let provider;
let user;
provider = new GoogleAuthProvider();
try {
await signInWithPopup(authService, provider).then(async (result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
user = result.user;
const docRef = doc(dbService, "users", user.email);
await getDoc(docRef).then(async (docSnap) => {
if (docSnap.exists()) {
dispatch(setLoginToken("login"));
dispatch(
setCurrentUser({
...docSnap.data(),
})
);
} else {
const usersRef = collection(dbService, "users");
await setDoc(doc(usersRef, user.email), {
uid: user.uid,
displayName: user.email.split("@")[0],
email: user.email,
photoURL: noneProfile,
createdAtId: Date.now(),
description: "",
bgURL: bgimg,
bookmark: [],
followAt: [],
follower: [],
following: [],
reNweet: [],
token: token,
});
dispatch(setLoginToken("login"));
dispatch(
setCurrentUser({
uid: user.uid,
displayName: user.email.split("@")[0],
email: user.email,
photoURL: noneProfile,
bgURL: bgimg,
description: "",
createdAtId: Date.now(),
bookmark: [],
followAt: [],
follower: [],
following: [],
reNweet: [],
})
);
}
});
});
history.push("/");
} catch (error) {
console.log(error);
alert("Google 로그인 오류");
}
};
return (
<button onClick={onSocialClick} name="google" className={styled.authBtn}>
<FcGoogle />
{newAccount ? "Google로 로그인 하기" : "Google로 가입하기"}
</button>
);
};
const [init, setInit] = useState(false);
const [userObj, setUserObj] = useState(null);
useEffect(() => {
// 유저 상태 변화 추적(로그인, 로그아웃, 어플리케이션 초기화 시)
authService.onAuthStateChanged(async (user) => {
if (user) {
setUserObj(user);
} else {
setUserObj(null);
}
setInit(true); // 어플리케이션이 언제 시작해도 onAuthStateChanged가 실행돼야 하기 때문에 true
});
}, []);
return (
<>
{init ? (
<AppRouters isLoggedIn={Boolean(userObj)} userObj={userObj}/>
) : (
<div className={styled.render__loading}>
<AiOutlineTwitter className={styled.render__logo} />
</div>
)}
</>
);
// 코드 생략
const errorMessages = {
"(auth/email-already-in-use).": "이미 가입이 되어있는 이메일입니다.",
"(auth/invalid-email).": "올바르지 않은 이메일 형식입니다.",
"(auth/weak-password)": "비밀번호를 최소 6글자 이상 입력해주세요.",
"(auth/wrong-password).": "이메일이나 비밀번호가 틀립니다.",
"(auth/too-many-requests)":
"로그인 시도가 여러 번 실패하여 이 계정에 대한 액세스가 일시적으로 비활성화되었습니다. 비밀번호를 재설정하여 즉시 복원하거나 나중에 다시 시도할 수 있습니다.",
"(auth/user-not-found)": "가입된 아이디를 찾을 수 없습니다.",
};
// ... 생략
} catch (error) {
const errorKey = Object.keys(errorMessages).find((key) =>
error.message.includes(key)
);
const errorMessage = errorKey ? errorMessages[errorKey] : error.message;
setError(errorMessage);
}