1차 프로젝트 - Wesop✨ (회원가입 모달창)

더미벨·2022년 7월 3일
0
post-thumbnail

상세페이지에 이어 회원가입페이지를 구현하게 되었다. 인스타그램 클론코딩 때도 한번 해보았으니 쉽겠지...라고 생각하며 호기롭게 내가 구현해보겠다고 했는데...ㅎ..
placeholder 이동하게 하는 거에서부터 코드를 완전히 갈아 엎은 수준이다. 그 부분은 그냥 포기할까도 생각했는데 막상 구현해놓고 보니 또 뿌듯하다^_^ 멘토님, 팀원분들이 도와주신 덕분이다.


📍회원가입 버튼 클릭시 모달창 열기


const SignUp = () => {
  const [modal, setModal] = useState(false);

  return (
    <>
      <div
        className="signUp"
        onClick={() => {
          setModal(true);
        }}
      >
        회원가입창
      </div>
      <div className="modal">
        {modal ? <Modal modal={modal} setModal={setModal} /> : null}
      </div>
    </>
  );
};

modal이라는 state를 하나 만들고, 회원가입 버튼을 클릭할 때 state값이 true로 바뀌도록 했다.
삼항연산자를 이용해 modal의 값이 true일 경우 모달창이 보이도록 작성했다.


📍 입력되는 input값 받아오기

const [userInfo, setUserInfo] = useState({
    email: '',
    password: '',
    passwordConfirm: '',
    lastName: '',
    firstName: '',
  });

  const { email, password, passwordConfirm, lastName, firstName } = userInfo;

  const changeUserInfo = (name, value) => {
    setUserInfo({ ...userInfo, [name]: value });
  };

  const validationUserInfo = (name, value) => {
    switch (name) {
      case 'lastName':
        changeUserInfo(name, value);
        break;

      case 'firstName':
        changeUserInfo(name, value);
        break;

      default:
        break;
    }
    return;
  };

  const handleChangeUserInfo = ({ target: { name, value } }) => {
    changeUserInfo(name, value);
    validationUserInfo(name, value);
  };

userInfo라는 state의 초기값에 각 input에 해당하는 key값을 넣어주고 다시 구조분해할당을 해주었다.


📍input창 컴포넌트화하기


1. placeholder 이동

처음에는 Modal 파일 내에서 state를 만들고 onchange 이벤트 발생시 함수를 실행시켰더니, 하나의 input창에만 입력해도 모든 placeholder가 이동하는 현상이 발생하였다.
input을 하나의 컴포넌트 파일로 빼고, state도 해당 파일 내에서 선언해준 뒤 map()함수와 상수데이터를 활용해 모달 파일 내에서 반복실행해주었다.

const Input = ({
  check,
  input_title,
  name,
  type,
  className,
  id,
  userInfo,
  id_error_message,
  pw_error_message,
}) => {
  const [placeholder, setPlaceholder] = useState('placeholder');
  const inputRef = useRef(null);

  const movePlaceholder = e => {
    if (inputRef.current.value.length === 0) {
      setPlaceholder('placeholder'); //input창에 아무것도 입력되지 않았을 때
    } else {
      setPlaceholder('placeholderHasValue'); // input창에 입력됐을 때
    }
  };

  return (
    <>
      <div className="inputBox">
        <p className={placeholder}>{input_title}</p>
        <input
          onChange={movePlaceholder}
          name={name}
          type={type}
          className={className}
          id={id}
          ref={inputRef}
        />
      </div>
    </>
  );
};
.placeholder {
        position: absolute;
        top: 60px;
        color: #666666;
        font-size: 20px;
        transition: all 0.1s;
      }
      .placeholderHasValue {
        color: #666666;
        transform: translateY(40px);
        font-size: 13px;
      }

placeholder와 placeholderHasValue라는 클래스를 각각 만들고, input창에 텍스트 입력시 클래스명이 placeholderHasValue로 바뀌도록 코드를 작성하였다.
input값에 접근하는 것은 useRef()를 이용해주었다.

2. 에러메시지 출력

삼항연산자를 이용하여
아이디: '@'와 '.com'이 포함되지 않을 때,
패스워드: '패스워드' 입력값과 '패스워드 확인' 입력값이 다를 때
에러메시지가 출력되도록 했다.

{userInfo.password.length === 0 ? (
        ''
      ) : userInfo.passwordConfirm.length === 0 ? (
        ''
      ) : userInfo.passwordConfirm === userInfo.password ? (
        ''
      ) : (
        <p className="errorMessage">{pw_error_message}</p>
      )}
      {userInfo.email.length === 0 ? null : userInfo.email.includes(
          '@' && '.com'
        ) ? null : (
        <p className="errorMessage">{id_error_message}</p>
      )}
const EMAIL_PASSWORD_INPUT = [
  {
    input_id: 1,
    input_title: '이메일 주소',
    type: 'text',
    name: 'email',
    className: 'input',
    id_error_message: '이메일 주소 형식에 맞지 않습니다. 다시 확인해주세요.',
  },
  {
    input_id: 2,
    input_title: '패스워드',
    type: 'password',
    name: 'password',
    className: 'input',
  },
  {
    input_id: 3,
    input_title: '패스워드 확인',
    type: 'password',
    name: 'passwordConfirm',
    className: 'input',
    pw_error_message: '이전에 사용했던 패스워드를 입력하세요.',
  },
];
const NAME_INPUT = [
  {
    input_id: 4,
    input_title: '성',
    type: 'text',
    name: 'lastName',
    className: 'lastName',
  },
  {
    input_id: 5,
    input_title: '이름',
    type: 'text',
    name: 'firstName',
    className: 'firstName',
  },
];

map()함수 실행시 해당되는 데이터만 출력되도록 하기 위해 상수데이터를 위와 같이 생성했다.
아이디/패스워드 입력 부분과 이름 입력부분의 레이아웃이 달라 상수데이터를 두개로 나누어 작성 후 각각 map함수를 실행시켜주었다.


📍 회원가입 정보 백엔드 서버로 보내기


const signUp = () => {
    fetch('http://10.58.4.206:8000/users/signup', {
      method: 'POST',
      body: JSON.stringify({
        email: email,
        password: password,
        last_name: lastName,
        first_name: firstName,
      }),
    })
      .then(response => response.json())
      .then(result => {
        if (result.message === 'SUCCESS') {
          alert('회원가입이 완료되었습니다.');
          setModal(false);
        }
      });
  };

위에서 저장한 input의 value값을 fetch()함수를 통해 해당 API주소로 보내주었다.
회원가입 성공시 출력되는 메시지를 활용해 회원가입이 완료되면 modal의 값을 false로 바꾸어 모달창이 닫히도록 구현하였다.

  const disableButton = () => {
    if (
      lastName === '' ||
      firstName === '' ||
      !email.includes('@' && '.com') ||
      password !== passwordConfirm
    ) {
      setDisabled(true);
    }
  };
<button className="signUpButton" onClick={signUp} disabled={disabled}>

버튼 비활성화를 위한 state 하나를 생성하고, 조건식으로 이루어진 함수를 통해 boolean값을 조정해준다. 버튼의 disabled 내에서 해당 함수를 실행시켜주면 이메일/패스워드/이름 중 하나라도 조건을 만족하지 못할 경우 버튼은 비활성화된다.
실제로도 이런식으로 프론트에서 먼저 유효성검사를 실행하고 백에서 한번 더 체크하는 방식으로 회원가입/로그인이 이루어진다고 한다.

profile
프론트엔드 개발자👩‍💻

0개의 댓글