react-transition-group

Hoon·2024년 8월 23일
0

React

목록 보기
15/15
post-thumbnail

react-transition-group 은 react 에서 좀 더 쉽게 애니메이션 효과를 구현할 수 있는 라이브러리로, react의 라이프 사이클 메서드와 함께 작동하여 react 구성 요소 간의 변화를 감지하고, 변화에 대한 애니메이션을 적용할수 있다.

install

$ yarn add react-transition-group
$ yarn add -D @types/react-transition-group

Components

Transition

react 컴포넌트가 mount , unmount , update 될 때 애니메이션을 적용할 수 있는 컴포넌트이다. react 라이프 사이클과 함께 작동하여 변화에 대한 애니메이션을 적용할 수 있다.

CSSTransition

CSS animation 을 적용할 수 있는 컴포넌트이다. CSS class 를 추가, 제거 또는 변경하여 애니메이션을 적용할 수 있다.

SwitchTransition

다른 컴포넌트로 전환될 때, 애니메이션을 적용할 수 있는 컴포넌트이다. key prop 을 이용하여 현재 보이는 컴포넌트와 새로운 컴포넌트를 전환할 때 애니메이션을 적용할 수 있다.

TransitionGroup

리스트를 관리할 때 사용되며, 리스트에 새로운 아이템이 추가, 제거 또는 변경될 때 애니메이션을 적용할 수 있다. 리스트 아이템을 key prop 으로 구분하고, 이를 기반으로 애니메이션을 적용한다.

use

Transition

import { Transition } from 'react-transition-group';

export default function Index() {
  const [isView, setIsView] = useState(false);

  const defaultStyle = {
    transition: `opacity 300ms ease-in-out`,
  };

  const transitionStyles: Record<TransitionStatus, CSSProperties> = {
    entering: { opacity: 1 },
    entered: { opacity: 1 },
    exiting: { opacity: 0 },
    exited: { opacity: 0 },
    unmounted: { opacity: 0 },
  };

  return (
    <S.Wrap>
      <S.Button onClick={() => setIsView((prev) => !prev)}>toggle</S.Button>

      <Transition in={isView} timeout={300} mountOnEnter unmountOnExit>
        {(state) => (
          // state: ** -> entering -> entered -> exiting -> exited -> **
          <S.Box style={{ ...defaultStyle, ...transitionStyles[state] }}>Animation Box</S.Box>
        )}
      </Transition>
    </S.Wrap>
  );
}
  • "state" : 상태값을 나타내며, entering , entered , exiting , exited, unmounted 가 존재한다.
  • "in" : in 값에 따라 state 상태값이 변경된다.
    - true : entering -> entered
    - false : exiting -> exited
  • "timeout" : 전환 효과가 재생되는 시간

  • "mountOnEnter" : 해당 옵션이 존재시 in 값이 true 가 되야만 렌더링 (이 옵션이 없다면 초기값이 false 일때도 dom tree에 존재하나 보이지만 않음)

  • "unmountOnExit" : 해당 옵션이 존재시 in 값이 false 가 될때, dom tree에서도 제거 (이 옵션이 없다면 true -> false 로 변경시 보이지만 않을 뿐 여전히 dom tree에 존재)

  • "on${status}" : 해당 상태로 변경된 직후 실행되는 함수

CSSTransition

import { CSSTransition } from 'react-transition-group';
import './Transition.css';

export default function Index() {
  const [isView, setIsView] = useState(false);

  return (
    <S.Wrap>
      <S.Button onClick={() => setIsView((prev) => !prev)}>toggle</S.Button>

      <CSSTransition in={isView} classNames="opacity" timeout={300} mountOnEnter unmountOnExit>
        <S.Box>Animation Box</S.Box>
      </CSSTransition>
    </S.Wrap>
  );
}

위의 Transition 컴포넌트 사용법과의 가장 큰 차이점은 classNames 를 props로 받는다는 것이다.
in , classNames 의 값에 따라 다음과 같은 순으로 class 명이 변경된다

${classNames}-enter -> ${classNames}-enter-active -> ${classNames}-enter-done -> ${classNames}-exit -> ${classNames}-exit-active -> ${classNames}-exit-done

이러한 class에 맞춰서 아래와 같이 css 를 작성하여 import해 사용하였다.

.opacity-enter {
  opacity: 0;
}

.opacity-enter-active {
  opacity: 1;
  transition: opacity 0.3s;
}

.opacity-exit {
  opacity: 1;
}

.opacity-exit-active {
  opacity: 0;
  transition: opacity 0.3s;
}

TransitionGroup

import { CSSTransition, TransitionGroup } from 'react-transition-group';
import './Transition.css';

export default function Index() {
  const [boxes, setBoxes] = useState<number[]>([]);

  const addBox = () => setBoxes((prev) => [...prev, Math.random()]);
  const deleteBox = (i: number) => setBoxes((prev) => prev.filter((_, idx) => idx !== i));

  return (
    <S.Wrap>
      <S.Button onClick={addBox}>add</S.Button>

      <TransitionGroup className="boxes">
        {boxes.map((box, idx) => (
          <CSSTransition key={idx} timeout={300} classNames="list">
            <S.Box onClick={() => deleteBox(idx)}>{box}</S.Box>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </S.Wrap>
  );
}

리스트를 그룹화하여 요소가 추가, 삭제 될때 리스트 요소에 대해 애니메이션을 적용한다.
따로 in 을 작성하지 않아도 된다.

.list-enter {
  transform: translateY(-20%);
  opacity: 0;
}

.list-enter-active {
  transform: translateY(0);
  opacity: 1;
  transition: all 0.3s;
}

.list-exit {
  transform: translateY(0);
  opacity: 1;
}

.list-exit-active {
  transform: translateY(-20%);
  opacity: 0;
  transition: all 0.3s;
}

SwitchTransition

여긴 잘 안써서, 나중에 쓸일 있으면 작성...

profile
개발자 Hoon입니다

0개의 댓글