React (3) - TypeScript 오늘 하루 안보기 팝업 만들기
2022. 4. 10. 17:50ㆍfront-end/React
728x90
React 로 '오늘 하루 안보기' 팝업을 만들었다.
시간을 세션이나, 로컬스토로지에 저장할 수 있는데, 로컬스토로지에 저장하였다.
우선 localStorage.setItem("PopUpNotShow", 시간); 으로 시간을 저장 한다.
그 다음 사용자가 접속 하였을 때, localStorage 에 저장된 PopUpNotShow을 가져온다.
localStorage.getItem("PopUpNotShow"); <- 코드를 보면 이 부분은 localStorage 에서 PopUpNotShow 값을 가져오는 것을 나타낸다.
PopUpNotShow를 현재 시간과 비교하여 현재 시간보다 더 높을 경우에는
아직 제한 시간이 다 지난 것이 아니기 때문에 팝업을 띄우지 않는다.
PopUpNotShow 이 없거나 현재 시간보다 적을 경우에는 제한 시간이 다 지난 것 이기 때문에 팝업을 띄운다.
아래 코드를 보면되는데, 작업한 그대로 복사해서 작성한 것이 아니라 css 쪽은 삭제 된 부분이 있어서 확인 후 코드를 수정하기 바랍니다.
import styled from "styled-components";
import { useEffect, useState } from "react";
function Popup() {
const [showPopup, setShowPopup] = useState<boolean>(false); // 팝업은 기본값을 안나오는 것으로 설정한다.
const [todayCheck, setTodayCheck] = useState<boolean>(false);
useEffect(() => {
const PopUpNotShow: string | null = localStorage.getItem("PopUpNotShow"); //localStorage에 PopUpNotShow 값을 가져온다.
const currentTime = Math.floor(new Date().getTime());
if (!PopUpNotShow) { // PopUpNotShow 없거나 처음 들어온 사람 - 팝업을 띄운다.
setShowPopup(true);
}
if (Number(PopUpNotShow) > currentTime) return; // 아닐경우에는 팝업을 안 띄운다.
if (Number(PopUpNotShow) < currentTime) { // 제한 시간이 지났으므로 팝업을 다시 띄운다.
setShowPopup(true);
}
}, []);
const handleClickClose = () => {
if (todayCheck) {
const expire = Date.now() + 43200000; //12시간 후에 PopUpNotShow 값이 사라진다.
const objString = JSON.stringify(expire);
localStorage.setItem("PopUpNotShow", objString); //localStorage에 "PopUpNotShow" key로 시간(objString)을 저장한다.
}
setShowPopup(false);
};
return (
<PopupLayer showPopup={showPopup}>
<Closebox>
<Input type="checkbox" id="checkbox" checked={todayCheck} onChange={() => setTodayCheck(!todayCheck)} />
<CheckBoxLabel htmlFor="checkbox" todayCheck={todayCheck}>
오늘 하루 안보기
</CheckBoxLabel>
<CloseButton onClick={handleClickClose} type="button" title="close">
X
</CloseButton>
</Closebox>
</PopupLayer>
);
}
const CloseButton = styled.button`
background-color: transparent;
color: inherit;
border-width: 0;
padding: 0;
cursor: pointer;
position: absolute;
right: 20px;
top: 18px;
display: block;
width: 24px;
height: 24px;
background: url("close 버튼 이미지") no-repeat center; //
background-size: 16px;
text-indent: -9999px;
`;
const Input = styled.input`
display: none;
`;
const CheckBoxLabel = styled.label<{ todayCheck: boolean }>`
position: relative;
display: inline-block;
padding-left: 34px;
align-items: center;
color: #aaa;
cursor: pointer;
line-height: 24px;
&:after {
position: absolute;
content: "";
display: block;
left: 0;
top: 0;
margin-right: 10px;
width: 24px;
height: 24px;
border: 1px solid #aaa;
border-radius: 5px;
${({ todayCheck }) => {
if (todayCheck)
return `background: url("check 이미지") no-repeat center;
background-size: 14px`;
}}
}
`;
const Closebox = styled.div`
position: absolute;
bottom: -30px;
left: 0;
width: 100%;
height: 60px;
background: #111;
padding: 18px 20px;
`;
const PopupLayer = styled.div<{ showPopup: boolean }>`
transition: all 0.3s;
position: fixed;
align-items: center;
background-size: auto 100%;
z-index: 10002;
visibility: visible; //transition 효과를 주려면 display 가 아니라 visibility로 제어한다
${({ showPopup }) => {
if (!showPopup) return `opacity:0; visibility:hidden; transition:all 0.3s;`;
}}
`;
export default Popup;
혹시 틀린 부분이나, 수정하면 좋을 것 같은 부분이 있으면 언제든지 조언 부탁드립니다.
728x90
'front-end > React' 카테고리의 다른 글
React (2) - TypeScript 에서 setState props로 넘길 때 Type 지정하는 법 (0) | 2022.04.04 |
---|---|
React (1) - redux-saga (0) | 2022.04.03 |