본문 바로가기
React.js

n일 동안 보지 않기 팝업(모달) 구현 ( react-cookie )

by Zih0 2022. 2. 27.

쿠키의 만료기간(expires) 옵션을 활용하여 "n일동안 보지 않기" 기능을 구현해봤습니다.

 

모달용 쿠키를 만들어 해당 쿠키가 존재하면 모달을 띄우지 않는 방식으로 간단하게 구현했습니다.

 

리액트에서 쿠키를 쉽게 접근하기 위해 react-cookie 라이브러리를 설치합니다.

npm install react-cookie

yarn add react-cookie

 

1. 모달

먼저 모달을 만듭니다.

import React from "react";
import styled from "styled-components";

const Container = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
`;

const ModalBackground = styled.div`
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.75);
  z-index: 1000;
`;

const ModalContainer = styled.div`
  z-index: 1001;
`;

const ModalContent = styled.div`
  width: 100%;
  background-color: #fff;
`;

const ModalCloseWrapper = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;

  p {
    cursor: pointer;
  }
`;

function Modal() {
  return (
    <Container>
      <ModalBackground />
      <ModalContainer>
        <ModalContent>
          Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ratione
          labore sint impedit, optio mollitia quae soluta possimus itaque
          obcaecati unde expedita laudantium ducimus distinctio quasi rerum
          molestiae velit, quibusdam cum.
        </ModalContent>
        <ModalCloseWrapper>
          <p>오늘 하루 더 이상 보지 않기</p>
          <p>닫기</p>
        </ModalCloseWrapper>
      </ModalContainer>
    </Container>
  );
}

export default Modal;

 

2. 모달 불러오기

모달을 불러와 state에 따라 모달을 띄울지 말지 설정해줍니다.

import { useEffect, useState } from "react";
import Modal from "./Modal";

export default function App() {
  const [openModal, setOpenModal] = useState(true);
  

  return (
    <div className="App">
      {openModal && <Modal closeModal={() => setOpenModal(false)} />}
    </div>
  );
}
...


interface IModalProps {
  closeModal: () => void;
}

function Modal({ closeModal }: IModalProps) {
  ...

	<Container>
      ...
        <ModalCloseWrapper>
          <p>오늘 하루 더 이상 보지 않기</p>
          <p onClick={closeModal}>닫기</p>
        </ModalCloseWrapper>
	  ...
	</Container>
  ...

저는 마운트 되자마자 모달이 떴으면 하므로, openModal의 초기값을 true 로 설정했습니다.

 

그리고 Modal의 닫기를 클릭하면 해당 모달이 꺼지도록 setOpenModal(false) 함수를 prop으로 보내줍니다.

여기까지는 일반적인 모달 ON/OFF 방식입니다.

 

이제 추가적으로 쿠키를 적용하여 쿠키가 만료되기 전까지는 모달이 안뜨도록 해보겠습니다.

 

3. 쿠키 설정

react-cookie 라이브러리 문서에 따라 App 컴포넌트를 <CookieProvider>로 감싸줍니다.

https://www.npmjs.com/package/react-cookie

 

react-cookie

Universal cookies for React. Latest version: 4.1.1, last published: 7 months ago. Start using react-cookie in your project by running `npm i react-cookie`. There are 469 other projects in the npm registry using react-cookie.

www.npmjs.com

import React from 'react';
import App from './App';
import { CookiesProvider } from 'react-cookie';

export default function Root() {
  return (
    <CookiesProvider>
      <App />
    </CookiesProvider>
  );
}

 

그리고 App 컴포넌트로 돌아와 react-cookie에서 제공하는 useCookies Hook을 이용해 쿠키 목록을 불러옵니다.

import { useCookies } from "react-cookie";

const [appCookies, setAppCookies] = useCookies();

 

(console.log(appCokies)를 해보시면 쿠키 목록을 확인하실 수 있습니다.)

 

만료시기를 설정하는 함수 getExpiredDate를 작성했습니다.

일 수를 입력하면, 현재 시간에서 해당 일수를 더한 시기를 반환합니다.

  const getExpiredDate = (days: number) => {
    const date = new Date();
    date.setDate(date.getDate() + days);
    return date;
  };

 

유효기간이 1일인 쿠키를 생성하고 모달을 닫는 함수를 작성합니다.

const closeModalUntilExpires = () => {
    if (!appCookies) return;

    const expires = getExpiredDate(1);
    setAppCookies("MODAL_EXPIRES", true, { path: "/", expires });

    setOpenModal(false);
};

 

useEffect로 해당 쿠키가 존재하면 모달이 안뜨고, 없으면 모달이 뜨도록 해주겠습니다.

hasCookie 라는 state를 추가적으로 생성하여 관리했습니다.

그리고 Modal 컴포넌트에 closeModalUnitlExpires 함수도 prop으로 넘겨

"오늘 하루 더 이상 보지 않기" 문구의 onClick 이벤트에 지정해줍니다.

import { useEffect, useState } from "react";
import { useCookies } from "react-cookie";
import Modal from "./Modal";

export default function App() {
  const [openModal, setOpenModal] = useState(true);
  const [hasCookie, setHasCookie] = useState(true);
  const [appCookies, setAppCookies] = useCookies();

  const getExpiredDate = (days: number) => {
    const date = new Date();
    date.setDate(date.getDate() + days);
    return date;
  };

  const closeModalUntilExpires = () => {
    if (!appCookies) return;

    const expires = getExpiredDate(1);
    setAppCookies("MODAL_EXPIRES", true, { path: "/", expires });

    setOpenModal(false);
  };

  useEffect(() => {
    if (appCookies["MODAL_EXPIRES"]) return;
    console.log(appCookies["MODAL_EXPIRES"]);
    setHasCookie(false);
  }, []);

  return (
    <div className="App">
      <button onClick={() => setOpenModal(true)}>모달 오픈</button>
      {openModal && !hasCookie && (
        <Modal
          closeModal={() => setOpenModal(false)}
          closeModalUntilExpires={closeModalUntilExpires}
        />
      )}
    </div>
  );
}

 

...

interface IModalProps {
  closeModal: () => void;
  closeModalUntilExpires: () => void;
}

function Modal({ closeModal, closeModalUntilExpires }: IModalProps) {
  return (
    <Container>
      <ModalBackground />
      <ModalContainer>
        ...
        <ModalCloseWrapper>
          <p onClick={closeModalUntilExpires}>오늘 하루 더 이상 보지 않기</p>
          <p onClick={closeModal}>닫기</p>
        </ModalCloseWrapper>
      </ModalContainer>
    </Container>
  );
}

export default Modal;

 

결과

오늘 하루 더 이상 보지 않기 문구를 클릭하면 아래와 같이 2월 28일 만료되는 쿠키가 생성됩니다. (작성일자 2월 27일)

그리고 새로고침 해보면 해당 모달이 더 이상 뜨지 않는 것을 확인할 수 있습니다.

 

코드샌드박스에 예시 코드를 올려놨습니닷. 코드샌박에선 쿠키를 못불러오네요.

로컬에서 해당 코드로 테스트해보시면 잘 되는 걸 확인하실 수 있습니다.

 

https://codesandbox.io/s/elegant-clarke-me3z8i?file=/src/App.tsx 

 

댓글