ReactはアニメーションのためにローレベルAPIとして ReactTransitionGroup
アドオンコンポーネントと、基本的なCSSアニメーションとトランジションを簡単に実行するために ReactCSSTransitionGroup
を提供しています。
ReactCSSTransitionGroup
#ReactCSSTransitionGroup
は ReactTransitionGroup
に基づいており、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>
);
}
});
注意: もし子要素を1つだけレンダリングするとしても、
ReactCSSTransitionGroup
の全ての子要素に提供しなければなりません。これが、Reactが、子要素が作成されているか、削除されたか、あるいはそのままであるか判断する方法です。
このコンポーネントでは、 ReactCSSTransitionGroup
に新しいアイテムが追加された次の瞬間に、 example-enter
CSSクラスと example-enter-active
CSSクラスを得ます。これは、 transitionName
propに基づく習慣です。
これらのクラスはCSSアニメーションやトランジションのトリガーとして使うことができます。例えば、以下のようにして、このCSSを加え、新しいリストアイテムを加えてみましょう。
.example-enter {
opacity: 0.01;
transition: opacity .5s ease-in;
}
.example-enter.example-enter-active {
opacity: 1;
}
アイテムを削除しようとしたときに、 ReactCSSTransitionGroup
がDOMの中にそれを保持していることに気づくでしょう。縮小化されていないReactのビルドとアドオンを使っているならば、Reactがアニメーションやトランジションが起こることを予期しているという警告が出るでしょう。これは、 ReactCSSTransitionGroup
がアニメーションが終わるまでDOM要素をページに保持し続けるからです。以下のCSSを加えてみましょう。
.example-leave {
opacity: 1;
transition: opacity .5s ease-in;
}
.example-leave.example-leave-active {
opacity: 0.01;
}
ReactCSSTransitionGroup
は transitionAppear
というオプションのプロパティを提供します。コンポーネントの最初のマウントの際に、更なるトランジションのフェーズを加えるためです。一般的には、 transitionAppear
が false
である最初のマウントの際にはトランジションのフェーズはありません。 transitionAppear
プロパティを値が true
である状態で渡す以下の例を見てみましょう。
render: function() {
return (
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
<h1>Fading at Initial Mount</h1>
</ReactCSSTransitionGroup>
);
}
最初のマウントの間、 ReactCSSTransitionGroup
は example-appear
CSSクラスを得て、次の瞬間に example-appear-active
CSSクラスを加えます。
.example-appear {
opacity: 0.01;
transition: opacity .5s ease-in;
}
.example-appear.example-appear-active {
opacity: 1;
}
最初のマウントの際には、 ReactCSSTransitionGroup
の全ての子要素は appear
しますが、 enter
はしません。一方、存在する ReactCSSTransitionGroup
に後から加えられた子要素は全て enter
しますが、 appear
はしません。
注意:
transitionAppear
プロパティはバージョン0.13
でReactCSSTransitionGroup
に加えられました。後方互換性を維持するために、デフォルトの値はfalse
に指定されています。
子要素にトランジションを適用するためには、 ReactCSSTransitionGroup
はすでにDOMにマウントされているか、 transitionAppear
プロパティに true
がセットされている必要があります。以下の例は動きません。 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>
);
}
上の例では、 ReactCSSTransitionGroup
にアイテムのリストをレンダリングしました。しかし、 ReactCSSTransitionGroup
の子要素は1個や0個のアイテムになり得ます。単一の要素が作成や削除のアニメーションを可能にします。同様に、現在の要素を置き換える新しい要素をアニメーションできます。例えば、以下のように、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>
);
}
});
もししたいならば、 enter
や leave
のアニメーションを無効にすることもできます。例えば、 enter
アニメーションは行いたいが、 leave
のアニメーションは行いたくない場合があるでしょう。しかし、 ReactCSSTransitionGroup
はDOMのノードが削除される前にアニメーションが終わるのを待ちます。ReactCSSTransitionGroup
がそれらのアニメーションを無効化するために、 transitionEnter={false}
や transitionLeave={false}
といったプロパティを追加することができます。
注意:
ReactCSSTransitionGroup
を使う際には、コンポーネントがトランジションが終わったことを検知したり、アニメーション関連でさらに複雑なロジックを実行するといったことはできません。更に細かな制御を求める場合は、トランジションをカスタムするために必要なフックを提供するローレベルのReactTransitionGroup
APIを使用できます。
ReactTransitionGroup
#ReactTransitionGroup
はアニメーションの基盤です。 React.addons.TransitionGroup
と同じくらい簡単に使用できます。これによって(上記の例のように)、宣言的に子要素が追加されたり削除されたりするときに、それらの上で特別なライフサイクルのフックが呼ばれます。
componentWillAppear(callback)
#このメソッドは TransitionGroup
の中で最初にマウントされるコンポーネントのために componentDidMount()
と同時に呼ばれます。これは、 callback
が呼ばれるまで、他のアニメーションが発生するのをブロックします。これは、 TransitionGroup
の最初のレンダリングのときにのみ呼ばれます。
componentDidAppear()
#componentWillAppear
が呼ばれて渡される callback
関数の後に呼ばれます。
componentWillEnter(callback)
#これは、存在する TransitionGroup
に追加されるコンポーネントのために、 componentDidMount()
と同時に呼ばれます。これは、 callback
が呼ばれるまで、他のアニメーションが発生するのをブロックします。これは、 TransitionGroup
の最初のレンダリングのときには呼ばれません。
componentDidEnter()
#componentWillEnter
が呼ばれて渡される callback
関数の後に呼ばれます。
componentWillLeave(callback)
#これは、 ReactTransitionGroup
から子要素が削除されたときに呼ばれます。子要素が削除されても、 ReactTransitionGroup
は callback
が呼ばれるまでDOMの中に子要素を保持し続けます。
componentDidLeave()
#これは、 willLeave
の callback
が呼ばれた際に呼ばれます( componentWillUnmount
と同時です)。
デフォルトで、 ReactTransitionGroup
は span
としてレンダリングされます。この動きは、 component
プロパティによって変更できます。例えば、 <ul>
をレンダリングしたい場合は以下のようになります。
<ReactTransitionGroup component="ul">
...
</ReactTransitionGroup>
Reactがレンダリングできる全てのDOMコンポーネントが使用できます。しかし、 component
はDOMコンポーネントである必要はありません。あなたが求めているどんなReactのコンポーネントにもなり得ます。あなた自身が記述したものにもです!
注意: v0.12以前では、DOMのコンポーネントを使用する際には、
component
プロパティがReact.DOM.*
を参照している必要がありました。コンポーネントが単純にReact.createElement
から渡されていたからです。これは今は文字列である必要があります。複合的なコンポーネントは複合的なものを渡す必要があります。
全ての付加的な、ユーザー定義のプロパティはレンダリングされたコンポーネントのプロパティになります。例えば、以下はCSSクラスとともに <ul>
をレンダリングする方法です。
<ReactTransitionGroup component="ul" className="animated-list">
...
</ReactTransitionGroup>