react-transition-groupの使い方メモ

記憶をなくした時のためのメモ。

react-transition-groupとは?

Reactでアニメーションを管理するためのライブラリです。

ただし、react-transition-group自体はアニメーション機能は提供していません。

react-transition-groupは「自分の書いたアニメーションを管理するためのライブラリ」であって、「アニメーションの機能を提供してくれるライブラリ」ではありません。

なので、アニメーションのCSSは自分で書かないといけません。

公式React Transition Group

具体的に何ができる?

すごく大雑把に言えば

  • 設定したstateが falsetrue になったら指定したclassを付与する
  • 設定したstateが truefalse になったら指定したclassを付与したのちに要素を削除する(もしくは削除しない)

みたいなことができるライブラリです。

4つのコンポーネント

公式に書いている通りですが、react-transition-groupでは

  • Transition
  • CSSTransition
  • SwitchTransition
  • TransitionGroup

という4つのコンポーネントが提供されています。

違い

前半2つは

  • 設定したstateが falsetrue になったら指定したclassを付与する
  • 設定したstateが truefalse になったら指定したclassを付与したのちに要素を削除する(もしくは削除しない)

みたいなことができるコンポーネントです。

 

後半2つは、前半2つを管理するためのコンポーネントです。

Transition と CSSTransitionの違い

CSSTransition は、Transitionの上位互換です。

TransitionでできることはCSSTransitionでも出来ます。

違いは

  • CSSTransitionではclassNamesという属性を指定できる
  • CSSTransitionではappearという遷移状態も追加される

の2点かと思われます。(後述します)

SwitchTransition と TransitionGroupの違い

  • 共通点:
    • 複数のTransitionCSSTransitionを管理するためのコンポーネント
  • 違い:
    • SwitchTransition:古い要素のアニメーションが終わってから新しい要素のアニメーションを行う
    • TransitionGroup:古い要素のアニメーションと新しい要素のアニメーションを同時に行う

使い方

Transition

Transitionコンポーネントの子要素にstateが渡ってきます。

import { Transition } from "react-transition-group";
function App() {
  const [animate, setAnimate] = useState(false);
  return (
    <>
      <button onClick={() => setAnimate((prev) => !prev)}>
        {animate ? "falseにする" : "trueにする"}
      </button>
      <Transition in={animate} timeout={2000} unmountOnExit>
        {(state) => {
          return <h1 style={{ backgroundColor: "red" }}>{state}</h1>;
        }}
      </Transition>
    </>
  );
Transition
  • animatefalseにすると・・・
    • stateexitingexitedと2秒かけて変化する
    • このgif動画ではunmountOnExittrueに設定しているため、exitedになった瞬間に要素自体も削除されるので、exitedは表示されていません
  • animatetrueにすると・・・
    • stateenteringenteredと2秒かけて変化する

 

以下、補足です。

  • TransitionコンポーネントにunmountOnExit={false}を指定すると、animatefalseにしたあとも要素が残り続ける
    • unmountOnExit={true}を指定すると、exitedに変化すると同時に要素自体も消える
      (ちなみにこの場合はunmountOnExit={true}をとわざわざtrueを指定しなくてもunmountOnExitだけでいい)
  • animateを最初からtrueに指定すると、最初からマウントされた状態(entered)からスタートする
    • animateを最初からtrueに指定した状態で、Transitionコンポーネントにappear={true}を指定すると、最初のマウント時にenteringenteredが実行されるようになる
  • timeoutの部分は、オブジェクトで指定することで個別に設定できる
    • 例えば、以下のように指定したりもできる。
      timeout={{
       appear: 500, //appearは最初にマウントされるときの秒数
       enter: 300,
       exit: 500,
      }}

 

このようにTransitionでは、inの値がtruefalseを切り替わることでstateが変化します。

この「stateが変化する」を特性を利用して「アニメーションに応用してね!」というのがTransitionコンポーネントです。

CSSTransition

さきほどのコードをCSSTransitionに変更したとしても、同じように動きます。

このようにCSSTransitionTransitionの上位互換なので、Transitionの代わりとしても使えます↓。

import { CSSTransition } from "react-transition-group";
function App() {
  const [animate, setAnimate] = useState(false);
  return (
    <>
      <button onClick={() => setAnimate((prev) => !prev)}>
        {animate ? "falseにする" : "trueにする"}
      </button>
      <CSSTransition in={animate} timeout={2000} unmountOnExit>
        {(state) => {
          return <h1 style={{ backgroundColor: "red" }}>{state}</h1>;
        }}
      </CSSTransition>
    </>
  );

 

ただ、このような使い方は(おそらく)しません。

CSSTransitionでは以下のようにclassNamesを使います。

import { CSSTransition } from "react-transition-group";
function App() {
  const [animate, setAnimate] = useState(true);
  return (
    <>
      <h2>現在のanimate:{animate ? "true" : "false"}</h2>
      <button onClick={() => setAnimate((prev) => !prev)}>
        {animate ? "falseにする" : "trueにする"}
      </button>
      <CSSTransition
        in={animate}
        timeout={2000}
        unmountOnExit
        classNames="fade"
      >
        <div> ←ここにclassが付与される
          <h2 style={{ backgroundColor: "red" }}>タイトルです</h2>
        </div>
      </CSSTransition>
    </>
  );

CSSTransition

例えば、 classNames="fade"と指定した状態で、inの値をfalsetrueに変更すると

fade-enter fade-enter-active

fade-enter-done

というクラスが付与されます。

 

逆に、inの値をtruefalseに変更すると

fade-exit fade-exit-active

fade-exit-done

というクラスが付与されます。

 

また、Transactionと違って

  • in={true}
  • appear={true}

の両方を指定することで、初回のマウント時のみ

fade-appear fade-appear-active

fade-appear-done

が付与されるようになります。

 

 

このようにTransitionでは、classNamesに設定した文字列がクラス名として付与されるようになります。

なのでそのクラス名のCSSをあらかじめ用意しておくと、目的のアニメーションを実現できます。

TransitionGroup

説明がムズかしいので、まず以下のコードを見てください。

function App() {
  const [dataList, setDataList] = useState(["あ", "い", "う"]);
  const textRef = useRef(null);
  return (
    <>
      <p>
        <input type="text" name="name" ref={textRef} />
      </p>
      <button
        onClick={() => setDataList((prev) => [...prev, textRef.current.value])}
      >
        追加する
      </button>
      <TransitionGroup>
        {dataList.map((data,i) => {
          return (
            <CSSTransition
              key={i}
              timeout={3000}
              unmountOnExit
              classNames="fade"
            >
              <div>
                <h3 style={{ backgroundColor: "red" }}>{data}</h3>
              </div>
            </CSSTransition>
          );
        })}
      </TransitionGroup>
    </>
  );

 

こんな感じで、CSSTransactioninを指定しなくても「要素が追加されたら自動的にクラスが付与される」みたいな挙動になります。

SwitchTransition

公式に良いサンプルがあったので、そのまま貼り付けます。

 

おわり

React
スポンサーリンク
この記事を書いた人
penpen

1991生まれ。WEBエンジニア。

技術スタック:TypeScript/Next.js/Express/Docker/AWS

フォローする
フォローする

コメント

タイトルとURLをコピーしました