피그마를 통해 내가 작업해야 할 페이지를 살펴보자. api를 연동하기 이전에 작업해야 할 부분은
이렇게 크게 5가지 이다.
이전에 멋쟁이 사자처럼 해커톤 프로젝트를 했을 때에는 1번, 2번까지는 코드를 짜봐서 수월하게 작업이 이루어졌지만 3 ~ 5번은 이번에 처음 시도하는 작업이어서 걱정이 되기도, 설레기도 하였다.
우선 모든 페이지들의 주소가 담긴 Routes 페이지를 하나 생성한다. 그곳에는 모든 페이지가 연결이 될 수 있게 path와 컴포넌트가 담긴 element 속성이 존재한다. 그리고 만든 페이지 내부 코드에는 useNavigate를 이용하여 페이지 이동이 가능하게 한다.
import { BrowserRouter, Route, Routes } from "reat-router-dom"; //리액트 라우터 돔 설치
import LoginPage from "../pages/LoginPage";
import SignUpPage from "../pages/SignUpPage";
const Router = () => (
<BrowserRouter>
<Routes>
<Route exact path="/LoginPage" element={<LoginPage />} /> // 여기서 path는 실제로 웹사이트에 입력할 이름을 의미하고, element는 가져올 컴포넌트를 의미한다.
<Route exact path="/SignUpPage" element={<SignUpPage />} />
</Routes>
</BrowserRouter>
import { useNavigate } from 'react-router'; // useNavigate를 import 해줘야 한다.
const SignUpPage = () => {
const navigate = useNavigate(); // 변수에 useNavigate 함수를 할당해준다.
const onClickBack = () => {
navigate("/MainPage"); // onClick event가 발생했을 경우 페이지를 이동하는 함수를 생성한다.
};
};
html을 이용하여 input 태그를 사용하는 것도 하나의 방법이긴 하다. 하지만 input 기능을 가진 하나의 컴포턴트를 이용하는 것이 최종 코드를 작성할 때 훨씬 가독성이 좋다. 또한 e.target을 이용하면 input을, e.target.value를 이용한다면 input에 입력되는 값을 함수를 이용해 제어할 수 있다. 이메일이나 비밀번호를 관리해야하기 때문에 useState를 이용한다면 좀 더 편리하다.
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [nameValid, setNameValid] = useState(false); // 유효성 검사를 하기 위해 필요함
const [emailValid, setEmailValid] = useState(false);
const [passwordValid, setPasswordValid] = useState(false);
const [notAllow, setNotAllow] = useState(true);
const handleName = (e) => {
setName(e.target.value);
setNameValid(true);
}
const handleEmail = (e) => {
setEmail(e.target.value);
const regex = /^(([^<>()\[\].,;:\s@"]+(\.[^<>()\[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
if(regex.test(email)) { // 정규표현식을 활용한 유효성 검사. test()를 활용하여 email이 해당 정규식에 포함이 되는지를 확인해서 true / false 를 return 한다.
setEmailValid(true);
} else {
setEmailValid(false);
}
}
const handlePassword = (e) => {
setPassword(e.target.value);
const regex = /^(?=.*[a-zA-z])(?=.*[0-9])(?=.*[$`~!@$!%*#^?&\\(\\)\-_=+])(?!.*[^a-zA-z0-9$`~!@$!%*#^?&\\(\\)\-_=+]).{7,20}$/;
if(regex.test(password)) {
setPasswordValid(true);
} else {
setPasswordValid(false);
}
}
.
.
.
<InputWrapper placeholder="닉네임" value={name} onChange={handleName} />
<InputWrapper placeholder="이메일" value={email} onChange={handleEmail} />
<InputWrapper placeholder="비밀번호" type="password" value={password} onChange={handlePassword} />
이번에는 useEffect를 이용하여 회원가입 및 로그인 페이지에 input이 모두 작성되었을 때 버튼이 활성화 되는 것을 구현할 것이다. notAllow는 현재 true를 기본값으로 가지고 있기 때문에 빈칸이 모두 작성된다면 false로 바꿀 것이다.
우선 nameValid, emailValid, passwordValid 모두 false를 default값으로 가지고 있기 때문에 이 모든 것들이 true가 된다면 setNotAllow(false)로 바꿔준다.
위에 handle~ 함수에서는 Valid를 바꿔주는 작업을 해줬기 때문에 위에 설명이 가능해진다. 코드를 살펴보자.
useEffect(() => {
if(emailValid && passwordValid && nameValid) {
setNotAllow(false);
return;
}
setNotAllow(true);
}, [emailValid, passwordValid, nameValid]);
버튼을 만든 컴포넌트에서는 input이 들어가면 색이 변경되어야 하는 기능을 넣어줘야 하기 때문에 ':disabled'를 사용한다.
// Button-index.jsx
:disabled {
background-color: rgba(86, 75, 154, 0.5);
}
// SignUpPage-index.jsx
<Button small disabled={notAllow} />
위에서 만든 Valid state를 이용하여 경고글을 만들면 된다. 자세히 살펴보면 우리는 if문을 사용해 정규표현식 형식에 맞지 않으면 Valid값을 false로 만들었기 때문에 이를 잘 이용하면 된다. 코드는 return 문에 작성하면 된다.
<WarnMessage>
{!passwordValid && password.length > 0 && password.length < 8 && (
<div>영문, 숫자, 특수문자 포함 최소 10자리 이상 입력해주세요.</div>
)}
</WarnMessage>