Reactとページトランジション
Reactを使ってページトランジションを実装したいならreact-transitionを使うといいです。このライブラリは名前も仕様もころころ変えすぎです。全てのリポジトリを修正するのにはとても時間がかかりました。
$ yarn add react-transitionリファレンスはこちら。
シンプルなルーティング
ここではコードをシンプルにする為にstate を使った簡単なルーティングを考えます。 onClick がバインドされた Button をクリックすることで <PageA /> と <PageB /> の2つのコンポーネントが切り替わる仕組みです。
import React, { Component } from 'react'class PageA extends Component {
render () {
return <div>page A</div>
}
}class PageB extends Component {
render () {
return <div>page B</div>
}
}export default class Root extends Component {
render () {
return (
<div>
{this.router}
<button onClick={this.onClick}>change</button>
</div>
)
} state = {page: 'a'} router () {
switch (this.state.page) {
case 'a': return <PageA />
case 'b': return <PageB />
}
} onClick () { this.setState({page: this.state.page === 'a' ? 'b' : 'a'}) } onClick = ::this.onClick
}
トランジションの実装
<Transition />はコンポーネントの出現と消失を props.in で受け取り、そのトランジションを制御します。トランジション処理をCssで実装するには<CssTransition /> を使用します。
これらを props.hildren でまとめて管理できるのが <TransitionGroup /> です。配列の要素の出現と消失を感知しトランジションしてくれます。
また、コンポーネント化したい場合にはJssを使用すると幸せになれます。例えば exit: classes.exit といった感じです。
import CSSTransition from 'react-transition-group/CSSTransition'
import TransitionGroup from 'react-transition-group/TransitionGroup'export default class Index extends Component {
render () {
return (
<div>
<TransitionGroup>
{this.router}
</TransitionGroup>
<button onClick={this.onClick}>change</button>
</div>
)
} get router () {
return (
<CSSTransition appear
key={this.state.page}
classNames={{
appear: 'appear',
appearActive: 'appear-active',
enter: 'enter',
enterActive: 'enter-active',
exit: 'exit',
exitActive: 'exit-active'
}}
timeout={{enter: 300, exit: 300}}>
{this.state.page === 'a' ? <PageA /> : <PageB />}
</CSSTransition>
)
} state = {page: 'a'} onClick () { this.setState({page: this.state.page === 'a' ? 'b' : 'a'}) } onClick = ::this.onClick
}
props.timeout はトランジションにかかる時間を意味します。これはCssのtransitionDuratoin と一致させる必要があります。
export default theme => {
return {
transitionLeave: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
opacity: 1,
width: '100%',
height: '100%'
},
transitionLeaveActive: {
opacity: 0,
transform: 'translate3d(0, -50%, 0)',
transitionDuration: '150ms'
}
}また、 exit が終了したタイミングで enter を呼び出すことをお勧めします。ページを遷移させてもスクロール値は0にならないからです。 exit のトランジションが実行されている時にスクロール値を0にすれば画面がちらつくことになります。 setTimeout を用いて enter が呼び出されるのと同じタイミングでスクロール値をリセットしています。
最後に props.appear ですが、これはデフォルトでtrueになっていないので注意です。
