react-transition-group の使い方

react-transition-group@^2で提供されているコンポーネントは

  • Transition
  • CSSTransition
  • TransitionGroup

の3つです。

Transition

Transitionは以下のようなプロパティを取ります。

childrenには(status: 'entering' | 'entered' | 'exiting' | 'exited') => JSX.Elementが渡されます。このstatusの状態を使ってクラス名や何かしらの属性を内部の要素に設定し、CSSなどを使ってアニメーションさせることができます。

inは内部コンポーネントを表示するかどうかです。infalseの時はexitingからexitedに向かい、trueの時はenteringからenteredに向かいます。1番最初は単に-ingなしでenteredexitedが直接設定されます。

timeoutは、status-ingである状態の時間(msec)を指定します。これはaddEndListenerを設定しない場合は必須になります。
addEndListenerは動的にtimeout時間を設定したい場合に使えます。例えば CSS のtransitionでアニメーションするような場合、その終わりにtransitionendイベントが発火しますが、その発火するまでの時間を使うことでtimeoutの代わりとすることができます。(修正箇所も減る)これは第一引数にchildren関数での戻り値の要素が渡り、第二引数では-ingの終わりということになるdone関数が渡ってきます。この渡ってきたルート要素からアニメーションする要素を取得し、transitionendイベントでdoneを読んで、-ingを終えるといったことができます。注意点として、このaddEndListenerinが変わるたびに毎回実行されます。そのためイベントの登録などをしている場合、実行回数分登録することになってしまうので、毎回doneを呼ぶタイミングでイベントの解除模するといいと思います。

mountOnEnterintrueになるまでマウントしなかったり、unmountOnExitexitedになる度アンマウントする為のプロパティです。消える時はアニメーションしなくていいみたいな場合に使うといい感じです。

またonEnteredonExitedなどを渡して完了した時に連動してある処理を行うこともできます。ほかに、

  • 直前の onEnter, onExit
  • -ingonEntering, onExiting

があります。

CSSTransition

内部的にはある程度設定済みのTransitionです。与えられたTransitionと同様のintimeoutやこのコンポーネント独自のclassNamesを元に主により高機能なクラス名の管理を行ってくれます。与えたclassNamesにサフィックスとして-enter, -enter-active, -enter-done, -exit, -exit-active, -exit-done, -appear, -appear-activeがルート要素に付くようになるので、それらのクラス名を使って CSS でアニメーションを設定します。

サフィックスの名前は以下のような状態だと思うといいかなと思います。

  • -enter-exitTransition-ingが付く直前に付き、-doneが付く時取り除かれる
    • またはonEnteronExitは呼ばれたタイミングからonEnteredonExitedが呼ばれるタイミングまで
  • -enter-active-exit-activeTransition-ingの別名
  • -enter-done-exit-doneTransition-edの別名

TransitionGroup

1つ1つがTransitionを持つような配列要素をレンダリングしたい時にそれらをラップするように使うだけです。注意点は2つあります。まず、各配列のルート要素はTransitionである必要があります。2つ目はTransitionにはinではなくkeyが必須です。またこれはユニークな値である必要があります。inTransitionGroupkeyから有無を判定して自動で設定してくれるので考えないで済みます。

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

(() => {
  <TransitionGroup>
    {items.map(item => {
      return 
        <CSSTransition key={item.id}>{
          status => {
            /* ... */
          }
        }</CSSTransition>
      );
    })
  </TranitionGroup>
})();