Reactとページトランジション

Fish
Fish
Aug 22, 2017 · 5 min read

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になっていないので注意です。

)
Fish

Written by

Fish

https://github.com/uufish

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade