본문 바로가기
🍀오늘도 삽질 중🍀/React.js

정규표현식을 이용한 sign up 구현하기-2

by 매진2 2023. 7. 13.
728x90

이전에 포스팅했던 계산된 속성명과 navigate는 제외하고 포스팅을 하려고 한다.

이번 포스팅에는 정규표현식을 이용한 이메일, 비밀번호 관리, 모달창 관리에 대해 이야기하려고 한다.

 

먼저 이메일과 비밀번호의 정규표현식은 아래와 같다.

이메일에는 앞에 영어가 들어가고 @ 이후 영어가 3글자 들어가고 끝난다.

이후 .을 찍으면 영어를 3글자를 더 써줘야 정규표현식에 맞춰 작성이 가능하다.

비밀번호는 10-16자로 이루어져 있고 영어, 특수문자, 숫자를 넣어줘야 정규표현식에 맞춰 작성할 수 있다.

  let emailRegular =
    /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

  let pwRegular = /^(?=.*[a-zA-Z])(?=.*[?!@#$%^*+=-])(?=.*[0-9]).{10,16}$/;

앞서 정규표현식을 변수 처리해준 내용에 .test(input의 값)을 붙여준다.

이 내용을 다시 변수 처리해주면 정규표현식을 쓸 때 깔끔하게 사용할 수 있다.

  const emailCondition = emailRegular.test(inputValue.email);
  const passwordCondition = pwRegular.test(inputValue.password);

이 정규표현식을 이용해서 조건에 맞으면 버튼이 활성화되게 하고

input에도 조건이 안 맞으면 빨간색이 뜨는 css 속성을 추가하고 조건에 맞으면 css 속성을 제거하도록 해주었다.

  const makeClassName = className => {
    return className ? 'inputTag' : 'inputTag red';
  };

            {INPUT_DATA.map(({ id, name, placeholder, className }) => {
              return (
                <input
                  key={id}
                  name={name}
                  placeholder={placeholder}
                  className={makeClassName(className)}
                  onChange={handleInput}
                />
              );
            })}
        <button
          className={`signUp ${signUpCondition ? 'greenButton' : ''}`}
          disabled={signUpCondition ? false : true}
          onClick={postUserSignUpData}
        >
          가입하기
        </button>

그리고 회원가입에 성공하면 환영 모달을 띄워주고 일정시간이 지난 후 바로 메인페이지로 넘어가게 하고 싶었다.

그래서 모달창을 JSX로 그려주고 state를 사용해 boolean 값으로 관리해주었다.

회원가입에 성공하면 보여야하기 때문에 초기값은 false로 설정했다.

isModalOpen이 true일 때 모달이 열려야하기때문에 &&연산자를 사용했다.

  const [isModalOpen, setIsModalOpen] = useState(false);

        {isModalOpen && (
          <div className="modalBlack">
            <div className="welcom">
              <p className="welcomTitle">환영합니다.</p>
              <p className="welcomText">
                <span className="textColor">꿀빵이와 앙꼬</span>의 회원이
                되었습니다.
              </p>
            </div>
          </div>
        )}

그리고 회원가입에 성공할 때 오는 백엔드의 값을 통해 state 값을 바뀔 수 있도록

setIsModalOpen으로 값을 true로 변경해주고

일정시간인 3초가 지나면 모달을 닫아주어야하기 때문에 setTimeout을 써주었다.

또한 모달을 닫아줌과 동시에 main으로 이동해야하기 때문에 navigate로 main을 연결해주었다.

  const postUserSignUpData = () => {
    fetch('api 주소', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(inputValue),
    })
      .then(response => {
        return response.json();
      })
      .then(data => {
        if (data.message === 'CREATE_USER_SUCCESS!') {
          setIsModalOpen(true);
          setTimeout(() => setIsModalOpen(false), 3000);
          setTimeout(() => navigate('/'), 3000);
        } else if (data.message === 'INVALID_EMAIL') {
          alert('다시 확인해주세요.');
        } 
      });
  };

body에 들어가있던 inputValue는

백엔드에게 보내줘야하는 key 갑과 value의 값이 동일해서 간단하게 적을 수 있었다.

 body: JSON.stringify(inputValue)

 

 

아래는 전체코드이다.

상수데이터를 컴포넌트 안에 선언한 이유는 삼항연산자를 통해 classname을 변경하기 위해서다.

import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './SignUpSecond.scss';

const SignUpSecond = () => {
  const [inputValue, setInputValue] = useState({});
  const [isModalOpen, setIsModalOpen] = useState(false);

  let emailRegular =
    /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

  let pwRegular = /^(?=.*[a-zA-Z])(?=.*[?!@#$%^*+=-])(?=.*[0-9]).{10,16}$/;

  const emailCondition = emailRegular.test(inputValue.email);
  const passwordCondition = pwRegular.test(inputValue.password);
  const pwCheckCondition = inputValue.pwCheck === inputValue.password;
  const nameCondition = inputValue.name?.length > 0;
  const phoneNumberCondition = inputValue.phoneNumber?.length === 11;

  const signUpCondition =
    emailCondition &&
    passwordCondition &&
    pwCheckCondition &&
    nameCondition &&
    phoneNumberCondition;

  const navigate = useNavigate();

  const handleInput = e => {
    const { name, value } = e.target;
    setInputValue({ ...inputValue, [name]: value });
  };

  const postUserSignUpData = () => {
    fetch('api 주소', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(inputValue),
    })
      .then(response => {
        return response.json();
      })
      .then(data => {
        if (data.message === 'CREATE_USER_SUCCESS!') {
          setIsModalOpen(true);
          setTimeout(() => setIsModalOpen(false), 3000);
          setTimeout(() => navigate('/'), 3000);
        } else if (data.message === 'INVALID_EMAIL') {
          alert('다시 확인해주세요.');
        } 
      });
  };

  const INPUT_DATA = [
    { id: 1, name: 'email', placeholder: '이메일', className: emailCondition },
    {
      id: 2,
      name: 'password',
      placeholder: '비밀번호',
      className: passwordCondition,
    },
    {
      id: 3,
      name: 'pwCheck',
      placeholder: '비밀번호 확인',
      className: pwCheckCondition,
    },
    { id: 4, name: 'name', placeholder: '이름', className: nameCondition },
    {
      id: 5,
      name: 'phoneNumber',
      placeholder: '휴대번호',
      className: phoneNumberCondition,
    },
  ];

  const makeClassName = className => {
    return className ? 'inputTag' : 'inputTag red';
  };

  return (
    <div className="signUpSecond">
      <div className="fullContainer">
        <p className="signUpTitle">회원가입</p>
        <div className="border" />
        <div className="full">
          <p className="info">회원정보</p>
          <div className="fullInput">
            {INPUT_DATA.map(({ id, name, placeholder, className }) => {
              return (
                <input
                  key={id}
                  name={name}
                  placeholder={placeholder}
                  className={makeClassName(className)}
                  onChange={handleInput}
                />
              );
            })}
          </div>
        </div>
        <button
          className={`signUp ${signUpCondition ? 'greenButton' : ''}`}
          disabled={signUpCondition ? false : true}
          onClick={postUserSignUpData}
        >
          가입하기
        </button>
        {isModalOpen && (
          <div className="modalBlack">
            <div className="welcom">
              <p className="welcomTitle">환영합니다.</p>
              <p className="welcomText">
                <span className="textColor">꿀빵이와 앙꼬</span>의 회원이
                되었습니다.
              </p>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default SignUpSecond;
728x90