アニメーション

Reactはアニメーションの低階層APIとしてReactTransitionGroupアドオンのコンポーネントと、 基本的なCSSのアニメーションとトランジションの実装を簡単にするReactCSSTransitionGroupを提供します。

高レベルAPI: ReactCSSTransitionGroup

ReactCSSTransitionGroupReactTransitionGroupを基盤として、 ReactのコンポーネントがDOMに差し込まれる際、または取り去られる際のCSSトランジションとアニメーション操作を簡単にてくれます。 これは、素晴らしいライブラリであるng-animateに影響を受けています。

はじめに

ReactCSSTransitionGroupは、ReactTransitionsへのインターフェースです。 これはアニメーションさせたい全てのコンポーネントを囲うシンプルな要素です。 下記は、リスト項目をフェードイン、フェードアウトさせる例です。

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

var TodoList = React.createClass({
  getInitialState: function() {
    return {items: ['hello', 'world', 'click', 'me']};
  },
  handleAdd: function() {
    var newItems =
      this.state.items.concat([prompt('Enter some text')]);
    this.setState({items: newItems});
  },
  handleRemove: function(i) {
    var newItems = this.state.items;
    newItems.splice(i, 1);
    this.setState({items: newItems});
  },
  render: function() {
    var items = this.state.items.map(function(item, i) {
      return (
        <div key={item} onClick={this.handleRemove.bind(this, i)}>
          {item}
        </div>
      );
    }.bind(this));
    return (
      <div>
        <button onClick={this.handleAdd}>Add Item</button>
        <ReactCSSTransitionGroup transitionName="example">
          {items}
        </ReactCSSTransitionGroup>
      </div>
    );
  }
});

注意:
例え単一の項目のみを描画するとしても、 ReactCSSTransitionGroupの全ての子に、key属性を提供しなければいけません。 これはReactが、子が差し込まれるのか、取り除かれるのか、そのままにするのかを決定するためです。

このコンポーネント内で新しい項目がReactCSSTransitionGroupに追加されると、 その項目はexample-enterのCSSクラスを取得し、 その後に追加されるとexample-enter-activeを取得します。(翻訳に自信なし) これは、transitionNameプロパティに基いて行われます。

これらのクラスを、CSSアニメーションまたはトランジションをトリガするのに使用することが出来ます。 例えば、このCSSを追加して新しい項目を追加してみて下さい。

.example-enter {
  opacity: 0.01;
  transition: opacity .5s ease-in;
}

.example-enter.example-enter-active {
  opacity: 1;
}

あなたは項目を削除した際に、ReactCSSTransitionGroupがその項目をDOM内に保持することに気が付くでしょう。 アドオンを使用したReactでminify無しのビルドを使用している場合、 「Reactはアニメーションとトランジションが発生することを期待していた」という旨の警告が表示されます。 これは、アニメーションが完了するまでReactCSSTransitionGroupがDOM要素をページ上に保持するためです。 このCSSを追加してみて下さい。

.example-leave {
  opacity: 1;
  transition: opacity .5s ease-in;
}

.example-leave.example-leave-active {
  opacity: 0.01;
}

動作させるためには、アニメーショングループはマウント済みでなければいけない

トランジションを子に対して適用するためには、 ReactCSSTransitionGroupは予めDOM内にマウントされていなければいけません。 下記の例は、新しい項目がReactCSSTransitionGroup内にマウントされるのでは無く、 ReactCSSTransitionGroupが新しい項目と一緒にマウントされるため動作しません。 この例と、前述した「はじめに」の例との違いを比較してみて下さい。

  render: function() {
    var items = this.state.items.map(function(item, i) {
      return (
        <div key={item} onClick={this.handleRemove.bind(this, i)}>
          <ReactCSSTransitionGroup transitionName="example">
            {item}
          </ReactCSSTransitionGroup>
        </div>
      );
    }, this);
    return (
      <div>
        <button onClick={this.handleAdd}>Add Item</button>
        {items}
      </div>
    );
  }

1つの項目、または項目が無い状態からのアニメーション

上記の例では、ReactCSSTransitionGroup内に項目のリストを描画していますが、 ReactCSSTransitionGroupの子を1つの項目、または無しにすることが可能です。 これは、単一の要素の差し込みまたは取り除きのアニメーションを可能にしてくれます。 同じように、新しい要素が入り現在の要素が消える置換アニメーションを作ることも可能です。 例えば、下記のようにシンプルな画像カルーセルを実装することが可能です。

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

var ImageCarousel = React.createClass({
  propTypes: {
    imageSrc: React.PropTypes.string.isRequired
  },
  render: function() {
    return (
      <div>
        <ReactCSSTransitionGroup transitionName="carousel">
          <img src={this.props.imageSrc} key={this.props.imageSrc} />
        </ReactCSSTransitionGroup>
      </div>
    );
  }
});

アニメーションの無効化

必要であれば、差し込みアニメーション、または取り除きアニメーションを無効にすることが出来ます。 例えば、差し込みはアニメーションさせて、取り除きのアニメーションはさせたくないと考えるかもしれませんが、 ReactCSSTransitionGroupはDOMノードが削除される前にアニメーションを待ち受けてしまいます。

transitionEnter={false}またはtransitionLeave={false}ReactCSSTransitionGroupに追加することで、 これらのアニメーションを無効化することが出来ます。

注意:
ReactCSSTransitionGroupを使用している場合、 トランジションが終了した、またはアニメーションに関する何らかのより複雑な処理が実行されている時に、 コンポーネントがその事を検知する方法は存在しません。 もし、よりきめ細かい制御をしたいのであれば、 トランジションをカスタマイズするのに必要なフックを提供するReactTransitionGroupの低レベルAPIを使用します。

低レベルAPI: ReactTransitionGroup

ReactTransitionGroupはアニメーションの基礎となるものです。 これは、React.addons.TransitionGroupとしてアクセス可能です。 子が宣言的にここから追加または削除されると(前述した例のように)、 特別なライフサイクルのフックが子(コンポーネント?)上で呼び出されます。

componentWillAppear(callback)
componentDidMount()と同時に、 TransitionGroup内で初期マウントされたコンポーネントのために呼び出されます。 これはcallbackが呼び出されるまで、他のアニメーションの発生をブロックし、 TransitionGroupの初期描画でのみ呼び出されます。
componentDidAppear()
componentWillAppear呼び出しで渡されたcallback関数の後に、これが呼び出されます。
componentWillEnter(callback)
componentDidMount()と同時に、 既存のTransitionGroupに追加されるコンポーネントのために呼び出されます。 これはcallbackが呼び出されるまで、他のアニメーションの発生をブロックし、 TransitionGroupの初期描画でのみ呼び出されます。
componentDidEnter()
componentWillEnter呼び出しで渡されたcallback関数の後に、これが呼び出されます。
componentWillLeave(callback)
ReactTransitionGroupから、子が削除された際に呼び出されます。 子が削除されても、ReactTransitionGroupcallbackが呼び出されるまで、それを保持します。
componentDidLeave()
willLeavecallbackが呼び出された際に呼び出されます。(componentWillUnmountと同時)

異なるコンポーネントを描画

デフォルトでReactTransitionGroupspanを描画します。 これは、コンポーネントにプロパティを提供することで変更可能です。 例えば、下記では<ul>を描画しています。

<ReactTransitionGroup component="ul">
  ...
</ReactTransitionGroup>

Reactが描画出来る各DOMコンポーネントで使用することが出来ます。 ただし、コンポーネントはDOMコンポーネントである必要はありません。 あなたが必要とするものであれば、自分自身で書いたReactのコンポーネントでも構いません。

注意:
v0.12より前のバージョンでは、DOMコンポーネントを使用する際は、 コンポーネントのプロパティは、React.DOM.*への参照である必要がありました。 コンポーネントは単純にReact.createElementに渡されるので、 今は文字列で無ければいけません。 混合のコンポーネントはファクトリーに渡されなければいけません。

加えて、ユーザー定義プロパティは描画されたコンポーネントのプロパティになります。 例えば、下記はCSSクラスのある<ul>を描画する際の方法になります。

<ReactTransitionGroup component="ul" className="animated-list">
  ...
</ReactTransitionGroup>

 Back to top

© 2013-2017 Facebook Inc.
Documentation licensed under CC BY 4.0.

このページは、ページトップのリンク先のReact内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • ドキュメントの情報が古い可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。