본문 바로가기
fastcampus

[패스트캠퍼스 수강 후기] 프론트엔드 인강 100% 환급 챌린지 38회차 미션

by 새우하이 2020. 10. 14.

Styled-components Dialog 만들기

dialog는 화면을 가리면서 나타나는 box를 나타낸다. 이 box안에서 사용자가 어떤 작업을 할 지 선택할 수 있다.

project에서 componentes디렉터리에 Dialog.js 컴포넌트를 만들어 준다.

그다음 코드의 상단에서 styled과 Button도 불러와준다.

그리고 어두운 배경부터 준비해준다.

const DarkBackGround = styled.div`
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
`;

그리고 나서 내부에 구현할 DialogBlock을 만들어준다.

const DialogBlock = styled.div`
  width: 320px;
  padding: 1.5rem;
  background: white;
  border-radius: 4px;
  h3 {
    margin: 0px;
    font-size: 1.5rem;
  }
  p {
    font-size: 1.125rem;
  }
`;

Dialog내부에서 사용할 제목이나 콘텐츠들을 const DialogTitle = styled.div``; 로 구현해서 설정할 수도 있지만 처음부터 DialogBlock에서 사용되는 h3태그에대해 지정하는 방법도 있다.

const ButtonGroup = styled.div`
  margin: 3rem;
  display: flex;
  justify-content: flex-end;
`;

Button들을 감싸줄 ButtonGroup을 설정해준다.

그리고 Dialog의 props로 받아올 것들을 추가해준다.

title,children, confirmText, cancelText

function Dialog({ title, children, confirmText, cancelText }) {
  return (
    <DarkBackGround>
      <DialogBlock>
        <h3>{title}</h3>
        <p>{children}</p>
        <ButtonGroup>
          <Button color="gray">{cancelText}</Button>
          <Button color="pink">{confirmText}</Button>
        </ButtonGroup>
      </DialogBlock>
    </DarkBackGround>
  );
}

cancelText와 confirmText의 기본값도 설정해준다.

Dialog.defaultProps = {
  confirmText: "취소",
  cancelText: "확인",
};

그리고 Button 컴포넌트에 대한 추가적인 설정이 필요한 경우 !important를 사용할 수도 있지만 이 것을 사용하는 것은 좋지 않다.

따라서 Button 컴포넌트를 상속받아서 새로운 styled컴포넌트를 생성해주고 이것을 Button 대신에 불러와준다.

const ShortMarginButton = styled(Button)`
  & + & {
    margin-left: 0.5rem;
  }
`;
function Dialog({ title, children, confirmText, cancelText }) {
  return (
    <DarkBackGround>
      <DialogBlock>
        <h3>{title}</h3>
        <p>{children}</p>
        <ButtonGroup>
          <ShortMarginButton color="gray">{cancelText}</ShortMarginButton>
          <ShortMarginButton color="pink">{confirmText}</ShortMarginButton>
        </ButtonGroup>
      </DialogBlock>
    </DarkBackGround>
  );
}

기능구현

App.js 상단에 useState를 불러주고 dialog라는 상태를 만들어준다. 기본값은 false로 준다.

그리고 onClick을 선언해주고 Button에 지정해준다.

import Dialog from "./components/Dialog";
.
.
function App() {
  const [dialog, setDialog] = useState(false);
  const onClick = () => {
    setDialog(true);
  };
  const onConfirm = () => {
    setDialog(false);
  };
  const onCancel = () => {
    setDialog(false);
  };

onConfirm과 onCancel도 구현해주고 이것들을 Dialog에 넣어준다.

<Dialog
          title="정말 삭제하시겠습니까?"
          confirmText="삭제"
          cancelText="취소"
          onCancel={onCancel}
          onConfirm={onConfirm}
          visible={dialog}
        >

visible이라는 속성하나에 dialog도 추가해줘야한다.

그리고 Dialog 컴포넌트에서 visible 값을 받아오게 한다음 onConfirm과 onCancel도 받아온다

그리고 만약 visible값이 없으면 null을 리턴해주고, ShortMarginButton에 onConfirm과 onCancel을 추가해준다.

function Dialog({
  title,
  children,
  confirmText,
  cancelText,
  visible,
  onConfirm,
  onCancel,
}) {
  if (!visible) return null;
  return (
    <DarkBackGround>
      <DialogBlock>
        <h3>{title}</h3>
        <p>{children}</p>
        <ButtonGroup>
          <ShortMarginButton color="gray" onClick={onCancel}>
            {cancelText}
          </ShortMarginButton>
          <ShortMarginButton color="pink" onClick={onConfirm}>
            {confirmText}
          </ShortMarginButton>
        </ButtonGroup>
      </DialogBlock>
    </DarkBackGround>
  );
}

Styled-component 트랜지션 구현하기

트랜지션 효과를 구현할 때는 css의 keyframes를 사용한다.

우선 Styled에서 keyframe을 사용하려면 keyframes를 불러와야한다.

import styled, { keyframes } from "styled-components";

fadeIn을 구현해주는데

const fadeIn = keyframes`
from{
    opacity:0;
}
to{
    opacity:1;
}
`;

from은 시작할 때와 to는 끝날 때 를 의미한다.

const slideUp = keyframes`
from {
    transform: translateY(200px);
}
to{
    transfrom:translateY(0px);
}
`;

slideUp은 위로 나타나는 효과임.

DarkBackground 에서는 fadeIn효과를 주고

animation-duration : 얼마나 지속될 지

animation-timing-function : ease-out 은 처음에 빨랐다가 나중에 느려지는것을 의미하고

animation-name 을 ${fadeIn}

animation-fill-mode: forwards 는 애니메이션이 끝나고 어떻게 할지 forwards는 유지를 의미함.

animation-duration: 0.25s;
  animation-timing-function: ease-out;
  animation-name: ${fadeIn};
  animation-fill-mode: forwards;

그리고 이 설정을 복사해서 DialogBlock에도 붙여넣어주고

animation-name을 slideup으로 설정해준다.

}
  animation-duration: 0.25s;
  animation-timing-function: ease-out;
  animation-name: ${slideUp};
  animation-fill-mode: forwards;
`;

이렇게 적용시켜보면 나타나는 모습에 트랜지션이 입혀져있는데, 사라질 때 트랜지션을 적용시키는것이 조금 복잡하다. 하지만 원리를 알면 어렵지 않다.

상태를 관리해야한다. 상태 관리를 위해 useState와 useEffect를 불러와준다.

animation을 보여주고 있다는 상태를 관리하는 animate라는 상태를 선언해주고,

상태가 true에서 false로 전환되고 있다는 상태를 관리해주는 localVisible가 필요하다.

Dialog.js

function Dialog({
  title,
  children,
  confirmText,
  cancelText,
  visible,
  onConfirm,
  onCancel,
}) {
  const [animate, setAnimate] = useState(false);
  const [localVisible, setLocalVisible] = useState(false);

그리고 useEffect를 사용해서 visible값이 true에서 false로 바뀔 때의 동작을 정의해준다.

만약 localVisible이 true고 현재 visible이 false면 true에서 false 바뀜을 의미하고

setAnimate(true);

setTimeout(() ⇒ setAnimate(false), 250);

animate를 true로 바꿔주고

0.25초 뒤에 animate를 false로 설정해주겠다는 의미이다.

setLocalVisible(visible)로 설정해주는데 visible값이 바뀔때마다 localvisible 값을 동기화 시켜 준다는 의미이다.

deps에는 localVisible과 visible을 넣어줘야 한다.

useEffect(() => {
    //만약 visible이 true -> false가 되는 시점에 동작
    if (localVisible && !visible) {
      setAnimate(true);
      setTimeout(() => setAnimate(false), 250);
    }
    setLocalVisible(visible);
  }, [localVisible, visible]);
if (!localVisible && !animate) return null;

그리고 null을 리턴하던 조건문도 바꿔줘야한다.

이제 결과를 확인해보면 삭제를 눌렀을때 0.25초 뒤에 사라진다. 이제 fadeOut과 slideDown을 구현해준다.

fadeIn 과 slideUp 을 복사해서 from 과 내부의 속성만 위치를 바꿔주면된다.

const fadeIn = keyframes`
from{
    opacity:0;
}
to{
    opacity:1;
}
`;
const fadeOut = keyframes`
from{
    opacity:1;
}
to{
    opacity:0;

}
`;
const slideUp = keyframes`
from {
    transform: translateY(200px);
}
to{
    transfrom:translateY(0px);
}
`;
const slideDown = keyframes`
from {
    transfrom:translateY(0px);
}
to{
    transform: translateY(200px);

}
`;

그리고 DarkBackground와 DialogBlock에서 특정 Props가 설정되면 fadeOut이나 slideDown을 보여준다

${(props) =>
    props.disappear &&
    css`
      animation-name: ${fadeOut};
    `}

DarkBackground 하단에 props를 받아와서 disappear가 활성화되면 styled의 css를 불러와 fadeOut효과를 넣는 작업이다.

${(props) =>
    props.disappear &&
    css`
      animation-name: ${slideDown};
    `}

DialogBlock에서도 마찬가지

DarkBackground 에서 disappear에서 visible이 false일때 disappear이 true가 되게, DialogBlock에서도 마찬가지로 설정해준다.

return (
    <DarkBackGround disappear={!visible}>
      <DialogBlock disappear={!visible}>

이렇게 까지 되면 fadeOut과 slideDown이 잘 설정된다.

실제로 true에서 false로 전환된 시점을 catch하기 위해 localVisible을 사용하는 것이다.

 

 

 

 

해당 내용은 아래 링크에서 수강할 수 있다.

프론트엔드 개발 올인원 패키지 with React Online. 👉https://bit.ly/2ETLEzm

 

프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스

성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.

www.fastcampus.co.kr

 

댓글