
로그인 페이지로 생애 첫 프로젝트를 시작했다.
로그인 페이지는 기존에 하던것과 다른 부분이 GET 요청 뿐이라서
어려움없이 진행할 수 있었던 것 같다.
기획 단계에서 로그인 페이지에 아이디 저장을 하자고 해서
localstorage를 이용해 아이디를 저장해두고
그 값을 defalut value로 불러와 구현을 하였다.
하지만 실제 프로젝트에는 제외하게 된 이유가 2가지가 있다.
첫번째는 추가로 defalut value에 있는 값과 한 글자라도 바뀌게 되면
아이디저장 체크박스가 해제되도록 하고 싶었는데 구현하기가 너무 까다로웠다.
두번째로는 defalut value로 관리를 하다보니
백엔드에게 데이터를 보낼때 인식을 못해서 값이 안 가는것이었다.
두번째 이유로 결국 아이디저장을 추후에 구현하는 것으로 했고..
이번엔 defalut value가 아닌 state로 구현해봐야겠다고 생각했다.
너무 아쉬워서 미완성이지만 코드라도 올려보려고 한다ㅜㅜ
import { useState } from 'react';
const Login = () => {
const [inputValue, setInputValue] = useState({});
const handleInput = e => {
const { name, value } = e.target;
setInputValue({ ...inputValue, [name]: value });
};
const saveIdLocal = e => {
if (e.target.checked === true) {
localStorage.setItem('ID', inputValue.id);
} else if (e.target.checked === false) {
localStorage.removeItem('ID');
}
};
return (
<div className="login">
<div className="inputContainer">
<input
name="id"
placeholder="아이디"
defaultValue={localStorage.getItem('ID')}
handle={e => {
return handleInput(e);
}}
/>
<div className="saveContainer">
<input
className="checkbox"
type="checkbox"
onClick={e => saveIdLocal(e)}
checked={localStorage.getItem('ID')}
/>
<p className="saveId" name="checkbox">
아이디 저장
</p>
</div>
</div>
</div>
);
};
export default Login;
정규표현식을 로그인에도 적용을 할까 고민을 했는데
회원가입에서 정규표현식을 사용해서 이중으로 쓸 필요가 없다고 생각해서
값만 적히면 바로 로그인 버튼이 활성화 될 수 있도록 구현했다.
const conditon = inputValue.id?.length > 0 && inputValue.pw?.length > 0;
<button
className={`loginButton ${conditon ? 'greenButton' : ''}`}
disabled={conditon ? false : true}
onClick={postUserData}
>
그리고 회원가입이 되어있는 유저인지 확인하기 위해
input에 적힌 ID와 password를 POST 요청을 통해 백엔드에게 보내주었다.
회원가입되어있는 회원이라면 jwt 토큰이 오고
그것을 localstorage에 저장하는 방법으로 로그인/로그아웃을 구현하였다.
로그인에 성공하면 바로 메인 페이지로 넘어가도록 navigate hook을 사용하였다.
const navigate = useNavigate();
const postUserData = () => {
fetch('http://10.58.52.243:3000/users/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: inputValue.id,
password: inputValue.pw,
}),
})
.then(response => {
return response.json();
})
.then(data => {
if (data.accessToken) {
localStorage.setItem('token', data.accessToken);
navigate('/');
} else if (data.message === 'USER_IS_NOT_VALID') {
setIsModalOpen(true);
}
});
};
<button
className={`loginButton ${conditon ? 'greenButton' : ''}`}
disabled={conditon ? false : true}
onClick={postUserData}
>
로그인
</button>
만약 백엔드의 데이터에 없는 아이디나 비밀번호를 입력하면 모달창을 띄웠다.
state로 boolean 값을 사용해 모달창을 관리해주었다.
const [isModalOpen, setIsModalOpen] = useState(false);
const postUserData = () => {
} else if (data.message === 'USER_IS_NOT_VALID') {
setIsModalOpen(true);
}
};
{isModalOpen && (
<div className="modalBlack">
<div className="modal">
<div className="text">
<p className="auch">앗!</p>
<p className="notFound">회원정보를 찾을 수 없습니다.</p>
<p className="notFound">아이디/비밀번호를 다시 확인해주세요.</p>
</div>
<button onClick={() => setIsModalOpen(false)}>확인</button>
</div>
</div>
)}
로그인페이지에서 마지막으로 구현한 것은 회원가입 버튼을 누르면
회원가입 페이지로 넘어갈 수 있도록 link 태그를 사용해주었다.
link 태그의 경우 조건 없이 페이지를 넘어갈 때,
navigate hook은 로그인, 회원가입처럼 조건이 있을 때 보통 사용한다.
아이디/비밀번호 찾기는 구현하지 못했다 ㅜㅜ
아래는 전체 코드이다.
import { Link } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import SignInput from '../components/SignInput';
import './Login.scss';
const Login = () => {
const [inputValue, setInputValue] = useState({});
const [isModalOpen, setIsModalOpen] = useState(false);
const navigate = useNavigate();
const conditon = inputValue.id?.length > 0 && inputValue.pw?.length > 0;
const handleInput = e => {
const { name, value } = e.target;
setInputValue({ ...inputValue, [name]: value });
};
const postUserData = () => {
fetch('http://10.58.52.243:3000/users/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: inputValue.id,
password: inputValue.pw,
}),
})
.then(response => {
return response.json();
})
.then(data => {
if (data.accessToken) {
localStorage.setItem('token', data.accessToken);
navigate('/');
} else if (data.message === 'USER_IS_NOT_VALID') {
setIsModalOpen(true);
}
});
};
return (
<div className="login">
<p className="title">로그인</p>
<div className="inputContainer">
<SignInput
className="id"
name="id"
placeholder="아이디"
type="text"
handle={e => {
return handleInput(e);
}}
/>
<SignInput
className="pw"
name="pw"
placeholder="비밀번호"
type="password"
handle={e => {
return handleInput(e);
}}
/>
</div>
<button
className={`loginButton ${conditon ? 'greenButton' : ''}`}
disabled={conditon ? false : true}
onClick={postUserData}
>
로그인
</button>
<div className="buttonContainer">
<Link to="/signUp">
<button className="admition">회원가입</button>
</Link>
<p>|</p>
<button className="findId">아이디 찾기</button>
<p>|</p>
<button className="findPw">비밀번호 찾기</button>
</div>
{isModalOpen && (
<div className="modalBlack">
<div className="modal">
<div className="text">
<p className="auch">앗!</p>
<p className="notFound">회원정보를 찾을 수 없습니다.</p>
<p className="notFound">아이디/비밀번호를 다시 확인해주세요.</p>
</div>
<button onClick={() => setIsModalOpen(false)}>확인</button>
</div>
</div>
)}
</div>
);
};
export default Login;
'🍀오늘도 삽질 중🍀 > React.js' 카테고리의 다른 글
| 정규표현식을 이용한 sign up 구현하기-2 (0) | 2023.07.13 |
|---|---|
| 전체동의, 부분동의가 있는 Sign Up 구현하기-1 (0) | 2023.07.11 |
| fetch 메소드로 백엔드랑 소통하기 (0) | 2023.06.22 |
| 댓글 컴포넌트화해 분리하고 props로 데이터 전달하기 (0) | 2023.06.19 |
| 댓글 기능 구현하기 (0) | 2023.06.19 |