이젠 loginpage에서 이메일,비밀번호 폼을 구현할 차례!
난 전에 input태그로만 했었는데, 대부분 submit 기능이 있는 form 태그를 사용한다고 한다.
//Loginpage.jsx
<form>
<label htmlFor="email" style={{ marginRight: "10px" }}>이메일</label>
<input id="email" type="text" placeholder="이메일(아이디)를 입력해주세요"></input>
<label htmlFor="pwd" style={{ marginRight: "10px" }}>비밀번호</label>
<input id="pwd" type="password" placeholder="비밀번호를 입력해주세요"></input>
<button style={{ marginTop: "30px" }}>로그인</button>
</form>
- htmlFor?
htmlFor에 input의 아이디나 네임을 적어 인풋과 연결.
이메일 글씨를 클릭하면 id가 email인 input에 focus됨.
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState("");
복잡한 form일 경우 if문으로 모든 걸 조건을 걸기엔 복잡하기에
react-hook-form이라는 라이브러리를 이용해줄 거임.
const {register,handleSubmit} = useForm();
return(
<input
id="email"
type="text"
placeholder="이메일(아이디)를 입력해주세요"
value={email}
onChange={(e) => setEmail(e.target.value)}
{...register("email", {
required: {
value: true,
message: "필수요소입니다.",
},
생략~
<input
id="pwd"
type="password"
placeholder="비밀번호를 입력해주세요"
value={pwd}
onChange={(e) => setPwd(e.target.value)}
{...register("pwd", {
required: {
value: true,
message: "비밀번호 입력해주세요.",
},
form에 onSubmit 이벤트가 발생하면 ,실행되는 함수인 handleSubmit에 onSubmitHandler를 지정해준다.
const onSubmitHandler=(data)=>{
console.log(data);
}
return(
<form onSubmit={handleSubmit(onSubmitHandler)}/>
)
그럼 이젠 data엔 내가 register로 등록한 email,pwd데이터들이 넘겨오기에 따로 state로 관리할 필요가 없으므로 value,onChange는 과감히 삭제!
<input
id="pwd"
type="password"
placeholder="비밀번호를 입력해주세요"
{...register("pwd", {
required: {
value: true,
message: "비밀번호 입력해주세요.",
},
const {retgister,handleSubmit,formState: { errors }}=useForm();
const onErrorHandler=(error)=>{
console.log(error,'error')
}
<form onSubmit={handleSubmit(onSubmitHandler,onErrorHandler)}/>
input에 아무값도 입력하지 않았을 경우에 error라고 console에 뜨게 해주자.
이때, register에서 등록한 validation 기준에 따라 handleSubmit 가 validation을 해주고 이때 발생한 에러는 register에서 등록한 message에 따라 formState.errors 에 저장된다.
input들 밑에 p태그로 이렇게 지정해준다.
<P style={{ fontSize: "12px", color: "red" }}>{errors?.email?.message}</p>
?.(옵셔널 체이닝) 문법
요즘 많이 쓰이는 jsp 문법이며,좌측항 값이 없으면 undefined를 반환한다.
위 코드로 보면 다음과 같다.
errors에 아무값이 없으면?-> undefined를 반환
errors.email이 있으면? -> message를 반환
errors.email이 없으면? -> undefined를 반환
따라서, 이메일이 빈칸일 경우 아래에
빨간 문구로 register에 등록한 message값인 '필수 요소입니다'가 뜬다!
axios를 이용해 서버와 연동해보자.
api같은 경우는 따로 폴더를 만들어서 쓰는게 좋다!
1] auth.js를 생성한 다음 다음과 같이 입력한다.
import axios from "axios";
export const signIn = async (email, password) => {
return await axios
.post("https://api.portal.bytesmix.com/account/signin", {
email,
password,
sid: "test",
})
.then((response) => response.data);
};
이때 저 url은 bytesmix.com에서 임의로 쓴 것!
2] LoginPage.jsx 수정
//서버로 요청보내기
const onSubmitHandler = async(data)=>{
const {email,pwd} = data;
await signIn(email,pwd); //auth.js에 있는 signIn
};
이때 처음에 pwd대신에 password로 썼다가 계속 오류났었다..알고보니 내가 지정한 pwd로 써줘야 했던거..!
3] 토큰을 이용한 로그인 방식
JWT(=Json Web Token)은
헤더, 내용, 서명이 '.(dot)'을 구분자로 하여 JWT 토큰 1개를 이룬다.
Header
: 어떤 알고리즘을 이용했는지,어떤 타입인지를 정의한다.
Payload
:내용에서는 전달하는 데이터를 포함한다.
SIGNATURE
: 인코딩된 Header "." Payload 그리고 secret이 필요하다.
서버가 가지고 있는 비밀키로 확인하여 인증된 사용자인지를 확인한다.
4] 이제 그럼 DarkModeContext처럼 로그인도 전 페이지에서 다 쓰이는 기능이니까 userContext를 지정해보자.
UserContext.jsx 생성
export const UserContext= createContext();
export const UserContextProvider = {{children}} =>{
const [user,setUser] = useState(null);
const updateUser = (userData)=>{ //userData: 서버로부터 받아온 data값을 setUser에 업뎃함.
setUser(updateUser);
}
return(
<UserContext.Provider value={{user,updateUser}}>{children}</>
이렇게 value에 속성을 넣어주면
LoginPage.jsx에서 다음과 같이 작성한다.
const { user, updateUser } = useContext(UserContext);
const onSubmitHandler = async(data) =>{
생략~~
const result=await signIn(email,pwd);
updateUser(result);
console.log(result?.data);
};
최상위에 덮어주기
//index.js
<UserContextProvider>
<App/>
</UserContextProvider>
마지막으로 이렇게 작성하면 console에 내가 입력한 이메일,비밀번호등 data가 담겨져 있는 걸 볼 수 있다.