본문 바로가기
Web/Frontend

[리액트] 토스트 메세지 만들기

by r4bb1t 2020. 10. 26.
반응형

game-jam-2020.kucc.co.kr/의 참가 신청 버튼을 누르면 '신청이 마감되었습니다.' 라는 토스트 메세지가 뜨도록 만들었다.

일단 토스트 컴포넌트에서 고려해야 할 것들을 먼저 생각했다.

  • 버튼을 누르면 보이기
  • 일정 시간이 지나면 숨겨지기
  • 보이고 숨겨질 때 애니메이션 넣기

토스트 컴포넌트 자체에 isActive (지금 메세지가 보이고 있는지) 라는 state를 넣으려고 했는데, 버튼으로 조작해야 하고, 이 페이지에서 토스트 메세지는 여기에서만 쓰니까 일단 페이지에 state를 만들었다.

const [isActive, setIsActive] = useState(false);
<Toast isActive={isActive} setIsActive={setIsActive} message="신청이 마감되었습니다." />
<S.JoinButton onClick={() => {setIsActive(true);}}> 참가 신청 </S.JoinButton>

 

토스트 컴포넌트에는 페이지에서 만들어준 state랑 state 세팅 함수를 props로 넘겨준다.

그리고 버튼을 누르면 isActive가 true가 되도록 했다.

 

import React, { useEffect } from "react";

import * as S from "./styles";

interface ToastProps {
  message: string;
  isActive: boolean;
  setIsActive: (a: boolean) => void;
}

const Toast: React.FC<ToastProps> = ({ message, isActive, setIsActive }) => {
  useEffect(() => {
    if (isActive === true)
      setTimeout(() => {
        setIsActive(false);
      }, 3000);
  });
  return <>{isActive ? <S.Toast show={true}>{message}</S.Toast> : <S.Toast show={false} />}</>;
};

export default Toast;

 

useEffect에서는 isActive가 업데이트될 때, 만약 isActive가 true라면 3000ms 뒤에 isActive를 false로 바꿔준다.

그리고 css에서 애니메이션을 넣고, isActive가 false일 때 안 보이게 해줄 것이다.

 

const fadein = keyframes`
  0% { top: 0px; opacity: 0; } 
  100% { top: -30px; opacity: 1; }
`;
const fadeout = keyframes`
  0% { top: -30px; opacity: 1; } 
  100% { top: 0px; opacity: 0; }
`;

interface SnackbarProps {
  show: boolean;
}

export const Snackbar = styled.div<SnackbarProps>`
  z-index: 100;
  position: absolute;
  visibility: ${(props) => (props.show ? "visible" : "hidden")};
  background-color: #333;
  color: #fff;
  text-align: center;
  border-radius: 30px;
  padding: 1rem;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
  font-size: 1.6rem;
  -webkit-animation: ${(props) =>
    props.show
      ? css`
          ${fadein} 0.5s, ${fadeout} 0.5s 2.5s
        `
      : ""};
  animation: ${(props) =>
    props.show
      ? css`
          ${fadein} 0.5s, ${fadeout} 0.5s 2.5s
        `
      : ""};
  animation-fill-mode: forwards;
`;

 

props로 show 인자를 받아오는데, 여기엔 isActive가 들어올 것이다.

show의 T/F 여부에 따라 visibility를 visible과 hidden으로 해주면 된다.

애니메이션도 show의 T/F 여부에 따라 넣어주는데, fadein은 아래에서 위로 올라오면서 불투명도가 점점 커지고, fadeout은 반대다.

0.5초동안은 fadein 애니메이션을 보여주고, 2.5초 delay된 fadeout 애니메이션을 0.5초 보여줘서 총 3초동안 fadein-내용표시-fadeout이 연결되게 한다.

끝~!

반응형

댓글