회사에서 특정페이지에 팝업창을 노출하는 기능을 개발할 필요가
생겨서 팝업창을 만들게 되었다.
요구사항은
1. 페이지 진입 시 팝업창 노출
2. 팝업창 닫기 버튼 추가
3. 팝업창 내 이미지 노출 (이미지는 수시로 변경될 것으로 추측)
4. 오늘 하루 그만보기 추가
1번은 팝업창을 상시로 띄우면 되는 부분이고, 3번에 필요한 이미지 영역을 잡고서 팝업으로 보여줄 필요가 있었다.
2,4번은 동일하게 닫기 기능 + 쿠키 및 localStoarge 사용으로 로컬에서 팝업창 노출시간을 설정하면 된다.
나중에는 특정경로애서 유입되는경우에만 팝업을 띄워야하는 이슈가 있어서 팝업창을 커스텀하기 편하게 직접 만들기로 결정하였다;
1. 팝업창 만들기
팝업창을 만들기 위해서는 2가지 방법이 있다.
1. 직접 만들기
2. react 컴포넌트 사용하기
REACT에서는 팝업창을 만들기 위한 컴포넌트를 지원한다.
react-modal
import Modal from 'react-modal';
REACT에서 동작하는 내장 컴포넌트라서 사용법도 간단한 팝업창을 만들기에 최적화 되어있다.
필자는 커스텀하기 위한 목적으로 직접 팝업창을 만들었다.
(팝업창 동작구조를 이해하지못한 사람이면 직접 소스를 짜보는게 좋다. -_-당연한 소리)
2. 팝업창 소스
import React, { useEffect } from 'react'
import styled from 'styled-components'
import PropTypes from 'prop-types'
import Portal from './portal'
import img from 'components/popup/img/1667.jpg'
function Modal({ className, onClose, maskClosable, closable, visible }) {
const onMaskClick = (e) => {
if (e.target === e.currentTarget) {
onClose(e)
}
}
// 이전방문 날짜
const VISITED_BEFORE_DATE = localStorage.getItem('VisitCookie')
// 현재 날짜
const VISITED_NOW_DATE = Math.floor(new Date().getDate())
// console.log(VISITED_BEFORE_DATE)
// console.log(VISITED_NOW_DATE)
// localStorage.removeItem('VisitCookie')
useEffect(() => {
// 팝업 오늘 하루닫기 체크
if (VISITED_BEFORE_DATE !== null) {
// 날짜가 같을경우 노출
if (VISITED_BEFORE_DATE === VISITED_NOW_DATE) {
localStorage.removeItem('VisitCookie')
onClose(true)
}
// 날짜가 다를경우 비노출
if (VISITED_BEFORE_DATE !== VISITED_NOW_DATE) {
onClose(false)
}
}
}, [VISITED_BEFORE_DATE])
// 하루동안 팝업 닫기
const Dayclose = (e) => {
if (onClose) {
onClose(e)
const expiry = new Date()
// +1일 계산
const expiryDate = expiry.getDate() + 1
// 로컬스토리지 저장
localStorage.setItem('VisitCookie', expiryDate)
}
}
const close = (e) => {
if (onClose) {
onClose(e)
}
}
return (
<Portal elementId="modal-root">
<ModalOverlay visible={visible} />
<ModalWrapper
className={className}
onClick={maskClosable ? onMaskClick : null}
tabIndex="-1"
visible={visible}
>
<ModalInner tabIndex="0" className="modal-inner">
<ModalInner2>
<ImgStyle>
<a href="https://www.pping.kr" rel="noopener noreferrer" target={'_blank'} cursor="pointer">
<img src={img} style={{ width: '100%', height: '100%' }} alt="" />
</a>
</ImgStyle>
{closable && (
<CloseStyle>
<Close className="modal-close" onClick={Dayclose}>
오늘 하루 닫기
</Close>
<Close className="modal-close" onClick={close}>
닫기
</Close>
</CloseStyle>
)}
</ModalInner2>
</ModalInner>
</ModalWrapper>
</Portal>
)
}
Modal.propTypes = {
visible: PropTypes.bool,
}
const ModalInner2 = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`
const ImgStyle = styled.div``
const CloseStyle = styled.div`
display: flex;
justify-content: space-between;
background-color: #282828;
width: 210px;
padding: 15px;
border-radius: 0 0 15px 15px;
color: #ffffff;
`
const Close = styled.span`
cursor: pointer;
`
const ModalWrapper = styled.div`
box-sizing: border-box;
display: ${(props) => (props.visible ? 'block' : 'none')};
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
overflow: auto;
outline: 0;
`
const ModalOverlay = styled.div`
box-sizing: border-box;
display: ${(props) => (props.visible ? 'block' : 'none')};
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 999;
`
const ModalInner = styled.div`
box-sizing: border-box;
position: relative;
// box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5);
// background-color: #fff;
// border-radius: 10px;
width: 360px;
max-width: 480px;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
padding: 40px 20px;
`
export default React.memo(Modal)
모달 라이브러리
- 팝업창 띄우기, 닫기 기능, 하루동안 안보기
오늘 하루안보기는 쿠키를 사용하거나 localStorage를 사용하는 방법이 있다.
localStorage가 import로 불러올 필요도 없고 사용방법이 간단하여 2번을 선택했다.
모달 뷰페이지
- 모달 호출 페이지
import React, { useEffect, useState } from 'react'
import Modal from 'components/popup/modal'
const Main = () => {
const [modalVisible, setModalVisible] = useState(true)
// const openModal = () => {
// setModalVisible(true)
// }
const closeModal = () => {
setModalVisible(false)
}
return (
<div>
<>
{modalVisible && (
<Modal visible={modalVisible} closable={true} maskClosable={true} onClose={closeModal}></Modal>
)}
</>
</div>
)
}
export default Main
변수는 오늘 하루 안보기 기능을 핸들링하기 위한 목적으로 사용한다.
방문날짜(오늘하루 안보기 클릭기준)가 있을 경우는 오늘날짜와 비교하여 팝업을 띄우고 아니면 고정으로 띄운다.
(자세한 내용은 주석참고)
3. 팝업창 실제 구현환경
끝.
'프론트엔드 > React' 카테고리의 다른 글
[프론트엔드] React Router v6 match.parms 사용방법 (0) | 2022.03.16 |
---|---|
[프론트엔드] React Router v6 업데이트 (0) | 2022.03.15 |
[프론트엔드] REACT ROUTER-TUTORIAL 오류 수정 (0) | 2022.03.14 |
[프론트엔드] REACT 프로젝트 초기환경 구성 (0) | 2021.12.13 |
[프론트엔드] React Project - GA API 개발 (0) | 2021.12.06 |