[React]modal window

이해용·2022년 7월 11일
0
post-thumbnail
post-custom-banner

Modal Window

사용자 인터페이스 디자인 개념에서 자식 윈도에서 부모 윈도로 돌아가기 전에 사용자의 상호동작을 요구하는 창을 말한다.

2차 프로젝트에서 메가박스에서는 로그인을 할 경우 사이트로 이동되는 것이 아닌 로그인 모달창(modal window)으로 로그인을 진행하기 때문에 만들게 되었다.

login modal window

modal 창을 만들 때 동기분의 블로그를 참고하여 만드니 아주 쉽게 되었으나 정리가 필요하다는 느낌이 들었다.

code

먼저 코드를 만들기 전 modal 창을 만들 때 nav에서 로그인 버튼을 클릭하면 modal 창을 만들게하고 modal 창이 종료되는 것은
1. modal 창 바깥을 클릭했을 때
2. esc버튼을 눌렀을 때
3. modal 창의 X 버튼을 눌렀을 때
이렇게 3가지 경우를 모두 생각해야했다.

Nav.js

const [isModalOpen, setIsModalOpen] = useState(false); // 처음은 false로 초기값을 설정하고 click을 했을 때 true로 변경하여 modal 창이 열리게 한다.

  const modalOpen = () => {
    setIsModalOpen(true);
  }; // modalOpen을 onClick안에 넣었을 때 ture가 될 수 있도록 변경
...
  
return (
...
<NavRightText onClick={localStorage.getItem('token') ? signOut : modalOpen}> //token이 없으면 modal 창 open 설정
	{localStorage.getItem('token') ? '로그아웃' : '로그인'} // token 없으면 로그인으로 문구 변경
</NavRightText>
{isModalOpen && <Login setIsModalOpen={setIsModalOpen} />} // isModalOpen 값이 false여야 Login component가 실행될 수 있도록 설정
...

1. modal 창 바깥을 클릭했을 때

Login.js

const Login = ({ setIsModalOpen }) => {
  const modalClose = e => {
    if (e.target === e.currentTarget) {
      setIsModalOpen(false);
    }
  };

  return (
    <LoginWrapper onClick={modalClose}>
      <LoginModal setIsModalOpen={setIsModalOpen} />
    </LoginWrapper>
  );
  
  const LoginWrapper = styled.section`
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.3);
    z-index: 10;
	`;

export default Login;
};

e.target 과 e.currentTarget의 차이?

e.target은 클릭했을 때 해당 클릭한 부분을 표시하고 e.currentTarget은 클릭한 전체를 감싸는 부분을 나타낸다.

해당 코드에서 e.currentTarget은 LoginWrapper styled component이며 e.target이 로그인화면의 바깥부분을 클릭해야 창이 닫힐 수 있다.

console.log(e.currentTarget) 결과
console.log(e.currentTaeget)

2. esc버튼을 눌렀을 때

LoginModal.js

const LoginModal = ({ setIsModalOpen }) => {
  useEffect(() => {
    const escKeyModalClose = e => {
      if (e.key === 'Escape') {
        setIsModalOpen(false); 
      } 
    }; // esc key를 눌렀을 때 Modal 창 close
    window.addEventListener('keydown', escKeyModalClose); // 위에 만들어 놓은 escKeyModalClose를 keydown했을 때 이벤트로 등록한다. 즉, esc를 눌렀을 때 modal창 종료
    return () => window.removeEventListener('keydown', escKeyModalClose); // 위의 이벤트를 제거
  }, [setIsModalOpen]);

  return (
    <LoginModalWrapper>
      <LoginHeader setIsModalOpen={setIsModalOpen} />
      <LoginBody />
    </LoginModalWrapper>
  );
};

const LoginModalWrapper = styled.header`
  position: fixed;
  width: 26.25rem;
  top: 50%;
  left: 50%;
  background-color: white;
  transform: translate(-50%, -50%);
  z-index: 20;
`;

export default LoginModal;

escape key?

잘못된 예

if (e.keyCode === 27) {
        setIsModalOpen(false); 
      } 

처음 코드를 만들었을 때 esc에 해당하는 27번의 아스키코드를 사용했으나 멘토님께서 현재 아스키코드를 사용하지 않는다고 하여 검색해보니 여러 자료들이 나와 답변을 활용하여 진행했다.

https://stackoverflow.com/questions/3369593/how-to-detect-escape-key-press-with-pure-js-or-jquery

keycode

3. modal 창의 X 버튼을 눌렀을 때

LoginHeader.js

const LoginHeader = ({ setIsModalOpen }) => {
  return (
    <LoginHeaderWrapper>
      <LoginTop>로그인</LoginTop>
      <ExitButton onClick={() => setIsModalOpen(false)}> 
        <AiOutlineClose color="white" size="16" />
      </ExitButton>
    </LoginHeaderWrapper>
  );
};

const LoginHeaderWrapper = styled.div`
  position: relative;
  width: 26.25rem;
  height: 2.813rem;
  background-color: ${props => props.theme.colors.purple};
`;

const LoginTop = styled.h3`
  padding: 0.938rem 1.25rem 0 1.25rem;
  color: ${props => props.theme.colors.white};
  font-size: 1.2rem;
`;

const ExitButton = styled.div`
  position: absolute;
  top: 0.938rem;
  right: 1.25rem;
  color: white;
  cursor: pointer;
`;

export default LoginHeader;
 

최종 화면

완성된 ModalWindow

reference
https://velog.io/@remon/React-Project-%EB%A6%AC%EB%B7%B0-%EC%93%B0%EA%B8%B0-%ED%8F%BC-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84-Form-%EC%97%B4%EA%B3%A0-%EB%8B%AB%EA%B8%B0
https://velog.io/@edie_ko/JavaScript-event-target%EA%B3%BC-currentTarget%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
https://opentutorials.org/course/1375/6761
https://developer.mozilla.org/ko/docs/Web/API/EventTarget/removeEventListener
https://webisfree.com/2019-12-30/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%A0%9C%EA%B1%B0-removeeventlistener
https://stackoverflow.com/questions/3369593/how-to-detect-escape-key-press-with-pure-js-or-jquery
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

profile
프론트엔드 개발자입니다.
post-custom-banner

0개의 댓글