記憶をなくした時のためのメモ。
react-transition-groupとは?
Reactでアニメーションを管理するためのライブラリです。
ただし、react-transition-group自体はアニメーション機能は提供していません。
react-transition-groupは「自分の書いたアニメーションを管理するためのライブラリ」であって、「アニメーションの機能を提供してくれるライブラリ」ではありません。
なので、アニメーションのCSSは自分で書かないといけません。
具体的に何ができる?
すごく大雑把に言えば
- 設定したstateが false → true になったら指定したclassを付与する
- 設定したstateが true→ false になったら指定したclassを付与したのちに要素を削除する(もしくは削除しない)
 
みたいなことができるライブラリです。
4つのコンポーネント
公式に書いている通りですが、react-transition-groupでは
- Transition
- CSSTransition
- SwitchTransition
- TransitionGroup
という4つのコンポーネントが提供されています。
違い
前半2つは
- 設定したstateが false → true になったら指定したclassを付与する
- 設定したstateが true→ false になったら指定したclassを付与したのちに要素を削除する(もしくは削除しない)
みたいなことができるコンポーネントです。
後半2つは、前半2つを管理するためのコンポーネントです。
Transition と CSSTransitionの違い
CSSTransition は、Transitionの上位互換です。
TransitionでできることはCSSTransitionでも出来ます。
違いは
- CSSTransitionでは- classNamesという属性を指定できる
- CSSTransitionでは- appearという遷移状態も追加される
の2点かと思われます。(後述します)
SwitchTransition と TransitionGroupの違い
- 共通点:
- 複数のTransitionとCSSTransitionを管理するためのコンポーネント
 
- 複数の
- 違い:
- 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コンポーネントにunmountOnExit={false}を指定すると、animateをfalseにしたあとも要素が残り続ける- unmountOnExit={true}を指定すると、- exitedに変化すると同時に要素自体も消える
 (ちなみにこの場合は- unmountOnExit={true}をとわざわざ- trueを指定しなくても- unmountOnExitだけでいい)
 
- animateを最初から- trueに指定すると、最初からマウントされた状態(- entered)からスタートする- animateを最初から- trueに指定した状態で、- Transitionコンポーネントに- appear={true}を指定すると、最初のマウント時に- entering→- enteredが実行されるようになる
 
- timeoutの部分は、オブジェクトで指定することで個別に設定できる- 例えば、以下のように指定したりもできる。
timeout={{ appear: 500, //appearは最初にマウントされるときの秒数 enter: 300, exit: 500, }}
 
- 例えば、以下のように指定したりもできる。
このようにTransitionでは、inの値がtrue↔falseを切り替わることでstateが変化します。
この「stateが変化する」を特性を利用して「アニメーションに応用してね!」というのがTransitionコンポーネントです。
CSSTransition
さきほどのコードをCSSTransitionに変更したとしても、同じように動きます。
このようにCSSTransitionはTransitionの上位互換なので、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>
    </>
  );

例えば、 classNames="fade"と指定した状態で、inの値をfalse→trueに変更すると
fade-enter fade-enter-active
↓
fade-enter-done
というクラスが付与されます。
逆に、inの値をtrue→falseに変更すると
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>
    </>
  );

こんな感じで、CSSTransactionでinを指定しなくても「要素が追加されたら自動的にクラスが付与される」みたいな挙動になります。
SwitchTransition
公式に良いサンプルがあったので、そのまま貼り付けます。
おわり
コメント