로그인이 되어 있지 않으면 다른 페이지에 접근 불가 처리 할거임
ProtectedRoute.jsx생성
import { Navigate } from "react-router-dom";
import { auth } from "../firebase";
//children하위 컴포넌트
const ProtectedRoute = ({ children }) => {
const user = auth.currentUser; //현재 접속 유저
if (user === null) {
//유저가 없으면 navigate로 login 이동
return <Navigate to="/login" />;
}
return children; //자식컴포넌트로 이동
};
export default ProtectedRoute;
Home.jsx에 로그아웃 버튼 추가
import { auth } from "../firebase";
const Home = () => {
//로그아웃 함수
const logOut = () => {
auth.signOut();
};
return (
<h1>
<button onClick={logOut}>Log Out</button>
</h1>
);
};
export default Home;
로그아웃 클릭 후 새로고침하면 Login 페이지로 이동한다.
App.jsx의 라우터에 ProtectdRoute로 Layout을 감싼다.
CreateUser.jsx
onSubmit 함수 catch문에 추가한다 .
에러가 발생하면 콘솔로 출력
회원가입 시 에러를 발생시켜봤음
에러가 출력되는것을 확인 할 수 있다.
콘솔을 setError로 바꿔준다.
submit 시 에러를 초기화 한다.
폼의 margin-bottom을 추가하여 좀 더 여백을 주었다.
에러 발생할 경우 아래와 같이 출력된다.
그리고 CreateUser.jsx에서 사용하는 styled 컴포넌트를 따로 분리하도록 함
import { styled } from "styled-components";
export const Wrapper = styled.div`
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
width: 420px;
padding: 50px 0px;
`;
export const Title = styled.h1`
font-size: 42px;
`;
export const Form = styled.form`
margin-top: 50px;
margin-bottom: 10px;
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
`;
export const Input = styled.input`
padding: 10px 20px;
border-radius: 50px;
border: none;
width: 100%;
font-size: 16px;
&[type="submit"] {
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
`;
export const Error = styled.span`
font-weight: 600;
color: tomato;
`;
export const Switcher = styled.span`
margin-top: 20px;
a {
color: #1d9bf0;
}
`;
CreateUser.jsx에서 사용하던 styled 컴포넌트 전체 삭제하고 import해준다
import {
Error,
Form,
Input,
Switcher,
Title,
Wrapper,
} from "../components/auth-components";
그리고
{error && <Error>{error}</Error>}
<Switcher>
이미 계정이 있습니까? <Link to="/login">로그인 →</Link>
</Switcher>
에러메세지 하단에 이미 계정이 있으면 로그인 페이지로 이동하게끔 링크 걸어둔다
스타일이 잘 적용되는지 확인해봐야함
로그인 페이지로 이동
Login.jsx
CreateUser.jsx를 복사해서 만들어서 수정함
import { useState } from "react";
import { auth } from "../firebase";
import { Link, useNavigate } from "react-router-dom";
import { FirebaseError } from "firebase/app";
import { signInWithEmailAndPassword } from "firebase/auth";
import {
Error,
Form,
Input,
Switcher,
Title,
Wrapper,
} from "../components/auth-components";
const Login = () => {
const navigate = useNavigate();
const [isLoading, setLoading] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const onChange = (e) => {
//이벤트 객체를 분리함 ( target -> name/value )
//console.log(e);
const { name, value } = e.target;
if (name === "email") {
setEmail(value);
} else if (name === "password") {
setPassword(value);
}
};
//console.log(name, email, password);
const onSubmit = async (e) => {
e.preventDefault();
setError(""); //에러 초기화
if (isLoading || email === "" || password === "") return; //만약 이름,이메일,패스워드가 공백이면 리턴함
//로그인 실행
try {
setLoading(true); //로딩 시작
//유저정보
const credentials = await signInWithEmailAndPassword(
auth,
email,
password
);
console.log(credentials.user); // 유저 정보 출력
navigate("/"); //로그인 완료 후 기본 페이지로
} catch (e) {
if (e instanceof FirebaseError) {
setError(e.code, e.message);
}
} finally {
setLoading(false);
}
};
return (
<Wrapper>
<Title>Login 𝕏</Title>
<Form onSubmit={onSubmit}>
<Input
onChange={onChange}
name="email"
value={email}
placeholder="Email"
type="email"
required
/>
<Input
onChange={onChange}
value={password}
name="password"
placeholder="Password"
type="password"
required
/>
<Input type="submit" value={isLoading ? "Loading..." : "Log in"} />
</Form>
{error && <Error>{error}</Error>}
<Switcher>
계정이 없으신가요? <Link to="/create-user">가입하기 →</Link>
</Switcher>
</Wrapper>
);
};
export default Login;
이 부분이 다름
존재하지 않는 메일로 로그인 시도를 해봤다.
아래에 오류가 뜨는것을 확인 가능함.
올바르게 입력 시 기본 페이지로 이동
그리고 로그인/ 회원가입 시 오류 발생할 경우 현재는 오류 메세지가 영어로 발생한다.
-> 그래서 에러 메세지가 출력될 때마다 case문으로 알맞는 한국어로 리턴되게 만든다.
export const errorMessageToKorean = (error) => {
switch (error) {
case "auth/invalid-login-credentials":
case "auth/invalid-credential":
case "auth/user-not-found" || "auth/wrong-password":
return "이메일 혹은 비밀번호가 일치하지 않습니다.";
case "auth/email-already-in-use":
return "이미 사용 중인 이메일입니다.";
case "auth/weak-password":
return "비밀번호는 6글자 이상이어야 합니다.";
case "auth/network-request-failed":
return "네트워크 연결에 실패 하였습니다.";
case "auth/invalid-email":
return "잘못된 이메일 형식입니다.";
case "auth/internal-error":
return "잘못된 요청입니다.";
default:
return "에러가 발생했습니다.";
}
};
Login.jsx과 CreateUser.jsx에서 import 후 사용한다.
에러 잘 출력되는지 확인하기
비밀번호 틀리게 입력했음
잘 출력됨을 확인 할 수 있다.