Life-Calendar#5 | 회원가입 기능 만들기

김하은·2022년 11월 22일
1

Project

목록 보기
4/18
post-thumbnail

📍 생각해보기
1. 회원 가입 input창 글자를 입력할때마다 value 값으로 인식되어야함.
2. validation (정규식) 체크

  • id:조건을 걸어 아이디 형태에 부합하지 않으면 alert 창으로 알림.
  • password: 조건을 걸어 비밀번호 형태에 부합하지 않으면 alert 창으로 알림.
  1. 기존 값에서 새로 적은 아이디의 상태값 변화 (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자리 지정

  • i : 전체에 대해서 대소문자를 구분하지 않음

🚩 정규식 메서드

📍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;
});
  • 입력하는 기존값과 , 입력후 의 상태관리를 위해 위와 같이 useState로 email,password,name 상태값을 바꾸는 로직을 적어두었다.
    그후 if (!emailCheck(email)) -> 입력값인 (email)이 emailCheck(적어둔 정규식) 에 맞지 않을시 alert 알림창으로 "이메일 형식이 일치하지 않습니다" 라고 알람이 뜬후 return 값으로 false 를 반환한다.
    또한, name 입력값이 없거나, 비어있을시 alert 로 "입력해 주세요" 라는 알람창이 뜨도록 구현하였다.
    비밀번호도 이와 같이 구현하였다.
    이후 input태그에 value 값을 넣고 , onChange 값으로 입력한 이벤트 값이 setChange 가 되어 상태 값을 바꿔주도록 로직을 구현하였다.
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>)}
)
  • 상태값에 대한 useState를 만들어 준후, onChange={onChangeConfirmPassword} 에 대한 함수값을 구현하였다.
    setConfirmPassword 로 새로 입력값에 대해 setPasswordCheck 를 한다.
    입력한 value 값이 password 랑 맞지 않으면 CheckMessage 가 나타나게 된다.

🚩 useCallbak


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;
`

다음에 할것. 로그인 페이지

profile
꾸준함을 이기는것은 없다

0개의 댓글