📍 생각해보기
1. 회원 가입 input창 글자를 입력할때마다 value 값으로 인식되어야함.
2. validation (정규식) 체크
- id:조건을 걸어 아이디 형태에 부합하지 않으면 alert 창으로 알림.
- password: 조건을 걸어 비밀번호 형태에 부합하지 않으면 alert 창으로 알림.
- 기존 값에서 새로 적은 아이디의 상태값 변화 (useState)
✅ 1. 먼저 회원가입 유효성에 대한 조건 값을 먼저 적어 두었다.
(공통 함수들을 common.js 라는 파일에 따로 적어 두었다.)
📁Common.js
L Common.js
//패스워드 체크 여부
export const PwExp =
/^(?=.*[a-zA-z])(?=.*[0-9])(?=.*[A-Z])(?=.*[$`~!@$!%*#^?&\\(\\)\-_=+]).{8,16}$/;
export const PwCheck = (password) => {
return PwExp.test(password) ? true : false;
}
// 이메일 체크 여부
const emailExp = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/;
export const emailCheck = (mail) => {
return emailExp.test(mail) ? true : false;
}
-> 비밀번호를 검증할 정규식 (함수 PwExp 로 선언 하였다.)
정규식 메서드에서 test() 는 "문자열에 일치하는 부분이 있는지 확인하고, true 혹은 false를 return" 하기 때문에
return 값으로 password 에 대한 정규식을 test 하고,
ture, false 값으로 리턴하게 작성하였다.
이메일도 위와 똑같이 작성해 주었다.
📍/^ : 시작
📍$/ : 끝
📍 [A-Za-z0-9] : 영문 대소문자 혹은 숫자로 시작
📍 ([-_.][A-Za-z0-9]) : 두 번째 글자부터는 영문 대소문자 혹은 숫자이며 - _ .이 들어갈 수 있음
📍 * : 문자 또는 숫자가 0개 이상 나타남
📍@가 중간에 반드시 들어가야 함
📍도메인 부분도 마찬가지로 영문 대소문자 혹은 숫자로 시작하며 그 다음부터-_.이 들어갈 수 있음
📍. 이 최소한 하나는 반드시 들어가야 함
📍.뒤에 com과 같은 최상위 도메인이 들어갈 자리 2-3자리 지정
📍exec() : 문자열에서 일치하는 부분을 찾음. 일치한 문자열 및 기억한 모든 부분 문자열을 배열로 반환하거나 일치하는 부분이 없을 경우 null을 return함
📍test() : 문자열에 일치하는 부분이 있는지 확인하고, true 혹은 false를 return
📍match() : 모든 일치를 담은 배열을 반환, 일치가 없으면 null return
📍search() : 문자열에서 일치하는 부분을 탐색함. 일치하는 부분의 인덱스를 리턴하거나, 일치가 없는 경우 -1을 반환함
📍split() : 문자열에서 일치하는 부분을 찾고, 그 부분을 대체 문자열로 대체함
✅ 2. 조건값 적어둔후 useState, onChange로 상태값 변경을 해주었다.
const Joininput = () =>
// 이름 , 비밀번호, 이메일 , 비밀번호 확인
import { PwCheck, emailCheck} from '../../Common/Common.js'
const [email, onChangeUserEmail] = useState("");
const [name, onChangeUserName] = useState("");
const [password, onChangeUserPasswrod] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
//비밀번호 유효성 검사
const [passwordCheck, setPasswordCheck] = useState(false);
const onSignHandler = useCallback((e) => {
const statusCheck = false;
if (!emailCheck(email)) {
if (!alert('이메일 형식이 일치하지 않습니다')) {
return statusCheck;
}
}
if (name == null || name === "") {
alert("이름을 입력해주세요.");
return statusCheck;
}
if (!PwCheck(password)) {
if (!alert('비밀번호 형식이 일치하지 않습니다.(대문자, 소문자, 특수문자 포함)'){
return statusCheck;
}
}
return true;
});
return(
<JoinFrom>
<div>
<input
type="email"
placeholder="이메일을 입력하세요"
autoComplete="off"
value={email}
onChange={(e) => {
onChangeUserEmail(e.target.value)}}
/>
</div>
<div>
<input
type="text"
placeholder="이름을 입력하세요"
autoComplete="off"
value={name}
onChange={(e) => {
onChangeUserName(e.target.value)}}
/>
</div>
<div>
<input
type="password"
placeholder="비밀번호를 입력하세요"
autoComplete="off"
value={password}
onChange={(e) => {onChangeUserPasswrod(e.target.value)}}
/>
</div>
✅ 3. 처음 비밀번호를 입력후 재확인 비밀번호를 입력했을때 일치하는지 체크.
const onChangeConfirmPassword = useCallback((e) => {
setConfirmPassword(e.target.value);
setPasswordCheck(e.target.value !== password);
},[password]);
return(
<div>
<input
type="password"
placeholder="비밀번호를 한번 더 입력해주세요"
autoComplete="off"
value={confirmPassword}
onChange={onChangeConfirmPassword}
/>
</div>
{confirmPassword && passwordCheck && (
<CheckMessage>비밀번호가 일치하지 않습니다.</CheckMessage>)}
)
useCallback의 첫번째 인자로는 인라인 콜백과 의존성 값의 배열을 받게 된다.
useCallback(fn, deps)
의존성 배열인 deps에 변경을 감지해야할 값을 넣어주게 되면 password가 변경될 때마다 콜백 함수를 새로 생성하게 된다.
✅ 4. 버튼을 누른후 입력 데이터 백엔드에 전달하기
5. 돌아가기 버튼
const register = (e) => {
if(!onSignHandler()){
return;
};
const data = {
id: email,
name: name,
password: password
}
axios.post('백엔드 api주소',data)
.then((response) => {
console.log('User profile', response.data.user);
alert('가입되었습니다.')
navigate("/")
}).catch(error => {
console.log('error', error.response);
alert(error.response.data.message);
});
};
return(
<button
type="submit"
onClick={() => {register()}}>
<It>가입하기</It>
</button>
<Linkbox>
<Link to="/"><Pt>돌아가기</Pt></Link>
</Linkbox>
)
</JoinFrom>
onClick 했을때 이메일, 이름, 비밀번호가 맞지 않을시 아무것도 return 해주지 않는다.
맞을시, 백엔드 api에 data 를 post 로 보내주고,
user의 정보를 response 받아온다.
정보를 받아오면 alert 창으로 '가입이 완료 되었다 '고 알려준다. 만약 error 가 있을시 alert 창으로 알려준다.
돌아가기 버튼을 누르면 로그인 페이지로 돌아간다.
import styled from 'styled-components';
import { Link, useNavigate } from 'react-router-dom';
import axios from 'axios'
import { useState, useCallback } from 'react';
import { PwCheck, emailCheck} from '../../Common/Common.js'
const Joininput = () => {
const navigate = useNavigate();
// 이름 , 비밀번호, 이메일 , 비밀번호 확인
const [email, onChangeUserEmail] = useState("");
const [name, onChangeUserName] = useState("");
const [password, onChangeUserPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
//비밀번호 유효성 검사
const [passwordCheck, setPasswordCheck] = useState(false);
const onChangeConfirmPassword = useCallback((e) => {
setConfirmPassword(e.target.value);
setPasswordCheck(e.target.value !== password);
},[password]);
const register = (e) => {
if(!onSignHandler()){
return;
};
const data = {
id: email,
name: name,
password: password
}
axios.post('백엔드 api',data)
.then((response) => {
console.log('User profile', response.data.user);
alert('가입되었습니다.')
navigate("/")
}).catch(error => {
console.log('error', error.response);
alert(error.response.data.message);
});
};
const onSignHandler = useCallback((e) => {
const statusCheck = false;
if (!emailCheck(email)) {
if (!alert('이메일 형식이 일치하지 않습니다')) {
return statusCheck;
}
}
if (name == null || name === "") {
alert("이름을 입력해주세요.");
return statusCheck;
}
if (!PwCheck(password)) {
if (!alert('비밀번호 형식이 일치하지 않습니다.(대문자, 소문자, 특수문자 포함)')) {
return statusCheck;
}
}
return true;
});
return(
<JoinFrom>
<div>
<input
type="email"
placeholder="이메일을 입력하세요"
autoComplete="off"
value={email}
onChange={(e) => {
onChangeUserEmail(e.target.value)}}
/>
</div>
<div>
<input
type="text"
placeholder="이름을 입력하세요"
autoComplete="off"
value={name}
onChange={(e) => {
onChangeUserName(e.target.value)}}
/>
</div>
<div>
<input
type="password"
placeholder="비밀번호를 입력하세요"
autoComplete="off"
value={password}
onChange={(e) => {onChangeUserPassword(e.target.value)}}
/>
</div>
<div>
<input
type="password"
placeholder="비밀번호를 한번 더 입력해주세요"
autoComplete="off"
value={confirmPassword}
onChange={onChangeConfirmPassword}
/>
</div>
{confirmPassword && passwordCheck && (
<CheckMessage>비밀번호가 일치하지 않습니다.</CheckMessage>)}
<button
type="submit"
onClick={() => {register()}}>
<It>가입하기</It>
</button>
<Linkbox>
<Link to="/"><Pt>돌아가기</Pt></Link>
</Linkbox>
</JoinFrom>
);
};
export default Joininput;
const JoinFrom = styled.div`
box-sizing: border-box;
max-width: 56rem;
max-height: 18.75rem;
width: 600px;
height: 300px;
margin: 30px;
text-align: center;
& input {
box-sizing: border-box;
width: 410px;
margin-bottom: 30px ;
border: none;
border-bottom: 4px solid #afafaf;
font-size: 0.875rem;
top:200px;
height: 65px;
}
& input::placeholder {
font-size: 25px;
color: #ccc;
}
& input:focus {
outline: none;
border: 1px solid #7784cc;
box-shadow: 0 0 0 0.1rem rgb(59 65 99 / 25%);
}
& button {
box-sizing: border-box;
width: 410px;
height: 70px;
margin: 0.2rem;
padding: 0.3rem 0;
border: none;
font-size: 0.875rem;
color: #fff;
background: #545454;
border-radius: 15px;
cursor: pointer;
}
& button:hover {
background: #B2B2B2;
}
& a {
display: block;
font-size: 0.775rem;
color: #666;
}
`;
const CheckMessage = styled.p`
width: 50%;
margin: 0 auto;
font-size: 0.875rem;
color: red;
text-align: left;
`;
const Linkbox = styled.div`
margin-left: 150px;
width: 150px;
height: 100px;
background-color: #8D9EFF;
text-decoration: none;
display: flex;
position: absolute;
margin-top: 20px;
`
const It = styled.div`
font-size: 30px;
margin-bottom: 2px;
`
const Pt = styled.div`
font-size: 30px;
text-decoration: none;
`
다음에 할것. 로그인 페이지