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

간단하게 Sign In 구현하기

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

로그인 페이지로 생애 첫 프로젝트를 시작했다.

로그인 페이지는 기존에 하던것과 다른 부분이 GET 요청 뿐이라서

어려움없이 진행할 수 있었던 것 같다.

 

기획 단계에서 로그인 페이지에 아이디 저장을 하자고 해서

localstorage를 이용해 아이디를 저장해두고

그 값을 defalut value로 불러와 구현을 하였다.

 

하지만 실제 프로젝트에는 제외하게 된 이유가 2가지가 있다.

첫번째는 추가로 defalut value에 있는 값과 한 글자라도 바뀌게 되면

아이디저장 체크박스가 해제되도록 하고 싶었는데 구현하기가 너무 까다로웠다.

두번째로는 defalut value로 관리를 하다보니

백엔드에게 데이터를 보낼때 인식을 못해서 값이 안 가는것이었다.

두번째 이유로 결국 아이디저장을 추후에 구현하는 것으로 했고..

이번엔 defalut value가 아닌 state로 구현해봐야겠다고 생각했다.

 

너무 아쉬워서 미완성이지만 코드라도 올려보려고 한다ㅜㅜ

import { useState } from 'react';

const Login = () => {
  const [inputValue, setInputValue] = useState({});

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

   const saveIdLocal = e => {
     if (e.target.checked === true) {
       localStorage.setItem('ID', inputValue.id);
     } else if (e.target.checked === false) {
       localStorage.removeItem('ID');
     }
   };

  return (
    <div className="login">
      <div className="inputContainer">
        <input
          name="id"
          placeholder="아이디"
          defaultValue={localStorage.getItem('ID')}
          handle={e => {
            return handleInput(e);
          }}
        />
       <div className="saveContainer">
          <input
            className="checkbox"
            type="checkbox"
            onClick={e => saveIdLocal(e)}
            checked={localStorage.getItem('ID')}
          />
          <p className="saveId" name="checkbox">
            아이디 저장
          </p>
        </div> 
      </div>
    </div>
  );
};

export default Login;

정규표현식을 로그인에도 적용을 할까 고민을 했는데

회원가입에서 정규표현식을 사용해서 이중으로 쓸 필요가 없다고 생각해서

값만 적히면 바로 로그인 버튼이 활성화 될 수 있도록 구현했다.

  const conditon = inputValue.id?.length > 0 && inputValue.pw?.length > 0;

      <button
        className={`loginButton ${conditon ? 'greenButton' : ''}`}
        disabled={conditon ? false : true}
        onClick={postUserData}
      >

그리고 회원가입이 되어있는 유저인지 확인하기 위해

input에 적힌 ID와 password를 POST 요청을 통해 백엔드에게 보내주었다.

회원가입되어있는 회원이라면 jwt 토큰이 오고

그것을 localstorage에 저장하는 방법으로 로그인/로그아웃을 구현하였다.

로그인에 성공하면 바로 메인 페이지로 넘어가도록 navigate hook을 사용하였다.

  const navigate = useNavigate();

  const postUserData = () => {
    fetch('http://10.58.52.243:3000/users/signin', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email: inputValue.id,
        password: inputValue.pw,
      }),
    })
      .then(response => {
        return response.json();
      })
      .then(data => {
        if (data.accessToken) {
          localStorage.setItem('token', data.accessToken);
          navigate('/');
        } else if (data.message === 'USER_IS_NOT_VALID') {
          setIsModalOpen(true);
        }
      });
  };
  
      <button
        className={`loginButton ${conditon ? 'greenButton' : ''}`}
        disabled={conditon ? false : true}
        onClick={postUserData}
      >
        로그인
      </button>

만약 백엔드의 데이터에 없는 아이디나 비밀번호를 입력하면 모달창을 띄웠다.

state로 boolean 값을 사용해 모달창을 관리해주었다.

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

  const postUserData = () => {

        } else if (data.message === 'USER_IS_NOT_VALID') {
          setIsModalOpen(true);
        }
  };

      {isModalOpen && (
        <div className="modalBlack">
          <div className="modal">
            <div className="text">
              <p className="auch">앗!</p>
              <p className="notFound">회원정보를 찾을 수 없습니다.</p>
              <p className="notFound">아이디/비밀번호를 다시 확인해주세요.</p>
            </div>
            <button onClick={() => setIsModalOpen(false)}>확인</button>
          </div>
        </div>
      )}

로그인페이지에서 마지막으로 구현한 것은 회원가입 버튼을 누르면

회원가입 페이지로 넘어갈 수 있도록 link 태그를 사용해주었다.

link 태그의 경우 조건 없이 페이지를 넘어갈 때,

navigate hook은 로그인, 회원가입처럼 조건이 있을 때 보통 사용한다.

아이디/비밀번호 찾기는 구현하지 못했다 ㅜㅜ

 

 

아래는 전체 코드이다.

import { Link } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import SignInput from '../components/SignInput';
import './Login.scss';

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

  const navigate = useNavigate();

  const conditon = inputValue.id?.length > 0 && inputValue.pw?.length > 0;

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

  const postUserData = () => {
    fetch('http://10.58.52.243:3000/users/signin', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email: inputValue.id,
        password: inputValue.pw,
      }),
    })
      .then(response => {
        return response.json();
      })
      .then(data => {
        if (data.accessToken) {
          localStorage.setItem('token', data.accessToken);
          navigate('/');
        } else if (data.message === 'USER_IS_NOT_VALID') {
          setIsModalOpen(true);
        }
      });
  };

  return (
    <div className="login">
      <p className="title">로그인</p>
      <div className="inputContainer">
        <SignInput
          className="id"
          name="id"
          placeholder="아이디"
          type="text"
          handle={e => {
            return handleInput(e);
          }}
        />
        <SignInput
          className="pw"
          name="pw"
          placeholder="비밀번호"
          type="password"
          handle={e => {
            return handleInput(e);
          }}
        />
      </div>
      <button
        className={`loginButton ${conditon ? 'greenButton' : ''}`}
        disabled={conditon ? false : true}
        onClick={postUserData}
      >
        로그인
      </button>
      <div className="buttonContainer">
        <Link to="/signUp">
          <button className="admition">회원가입</button>
        </Link>
        <p>|</p>
        <button className="findId">아이디 찾기</button>
        <p>|</p>
        <button className="findPw">비밀번호 찾기</button>
      </div>
      {isModalOpen && (
        <div className="modalBlack">
          <div className="modal">
            <div className="text">
              <p className="auch">앗!</p>
              <p className="notFound">회원정보를 찾을 수 없습니다.</p>
              <p className="notFound">아이디/비밀번호를 다시 확인해주세요.</p>
            </div>
            <button onClick={() => setIsModalOpen(false)}>확인</button>
          </div>
        </div>
      )}
    </div>
  );
};

export default Login;

 

728x90