はじめに
少し期間が空いてしまいましたが、ブログを更新します。
今回は理解できていれば簡単なのに、なかなか実装できなかったReactアニメーションについてです。
これが何でかすご〜く苦労したんですね…
筆者自身が詰まったところから紐解く形で解説を載せていきたいと思います。
Counterサンプルにアニメーションを追加しよう!
まずはネタとして前回まで基礎を学ぶのに利用したCounterサンプルを利用します。
元々のCounterサンプルとは以下のものになります。

実装されている機能としては下記の4つになります。
- 「+」ボタンを選択するとClick数が+1される
- 「-」ボタンを選択するとClick数が-1される
- 「Increment if odd」ボタンを選択するとClick数が奇数のときのみ+1される
- 「Increment async」ボタンを選択すると1秒後にClick数が+1される
これに次の機能を1つ追加します。
- 「Show Toast」ボタンを選択するとToastが表示される
- 「Show Toast」ボタンを連打すると追加でToastが表示される
「Toast って何だろう…!?」と思う人もいるかもしれませんので、念のため説明します。
簡単に言うと、「ユーザにポップアップのような形で知らせるもの」です。
Androidユーザなら必ず見たことがあるはずです。(Android Developers Toasts)
今回目指す完成図は下記になります。

フォルダ構成
まずは例によってフォルダ構成を見ていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Toast表示のActionを追加
さて、まずはToastを表示するためのActionを追加しましょう。
1 2 3 4 5 6 7 8 9 10 | |
おわかりの通り、showToastがそのActionに該当します。
Toast表示Action発行後のReducer処理
続いて、Reducerの処理を書いていきます。
機能要件にあった通り、ボタンを連打することで複数のToastを表示します。
後で詳細を説明しますが、個々のToastを区別する必要があるため、固有値を付与します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
それぞれ説明します。
追加(1):
今回は簡単のため各Toastに与えるために固有値をnumとして定義し、初期値を0とします。
これをボタンタップ時にカウントアップして、そのnumを付与してToastを作成することで個々を区別することができます。
追加(2):
他のボタンをタップしたときにstate.numがリセットされてしまわないように、...stateを追加して、変化のない値も丸々返すようにしています。
追加(3):
Toast表示Actionがdispatchされた後に検知して、新たなnum値を返却するために追加しました。
Toast Componentの作成
今回、最も重要なComponentであるToast Componentを作成していきましょう。
Reactで簡単にアニメーションを作成可能なreact-addons-css-transition-groupのReactCSSTransitionGroupを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
ReactCSSTransitionGroup Componentの各パラメータは次の通りの意味です。
- transitionName: 基本となるアニメーション対象要素の名称
- transitionEnterTimeout: 要素が追加された後のタイムアウト時間
- transitionLeaveTimeout: 要素が消えた後のタイムアウト時間?
CSSでもアニメーションを追加するので、transitionEnterTimeoutやtransitionLeaveTimeoutが不要なんじゃないかと思ったりしたのですが、これらをつけないとエラーが出ます。
ReactCSSTransitionGroupの子要素としてToast表示したいDOM要素を追加します。
この子要素にkeyパラメータとしてnumを渡しています。
これによってボタン連打で追加される各DOM要素が固有の要素であることを区別しています。
keyの重要性については、React.jsの地味だけど重要なkeyについてを見ることをオススメします。
keyにnumを渡したいので、ToastのpropTypesにnum: React.PropTypes.number.isRequiredと定義しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
アニメーションを実行するにはcssファイルでスタイルをつけることも必要です。
それぞれ説明します。
.toats-group
これは単にToast全体の表示位置を右上に固定したかったため追加したスタイルになります。.toast
これはToastのデザインです。.toast:first-child
Toast要素は必ず1つ残り続けてしまうため、1番目の要素は非表示としています。.example-enter
Toastの表示し始めの透明度を設定しています。.example-enter.example-enter-active
Toast表示アニメーションになります。.example-leave
Toastの消え初めの透明度を設定しています。.example-leave-active
Toastの非表示アニメーションになります。
Counter ComponentのボタンからToast表示までの流れ
Toast Componentの作成が完了したので、これをCounter Componentから呼び出すように実装していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
1つ1つ説明します。
追加 (1):
numはReducerで変更された新しいstateのnumを受け付けるためにpropTypesに追加しました。
onShowToastはボタンクリック時にToast表示アクションの実行を受け付けるためにpropTypesに追加しました。
追加 (2):
ボタンアクションで実行するための追加です。
追加 (3):
Toast Componentの描画メソッドです。
1つ目の要素は非表示にCSSで設定しているので、初めから描画してしまって問題ありません。
追加 (4):
新たにpropTypesとして追加したnumとonShowToastを利用するために書いています。
追加 (5):
ボタンクリック処理とToast描画処理を書いています。
Toastので位置はCSSで右上固定にしてあるので、DOM位置がどこになろうと問題ありません。
Store周りの修正
最後にStore周りの修正です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
ここではmapStateToPropsContainerとmapDispatchToPropsContainerを実装しているので、Reducerで新たに作成されたstateを受け取ります。
それを適切にCounter Componentに渡す必要があります。
追加 (1):
Toast表示アクションをdispatchに流し込む必要があるので、showToastをaction.jsからimportしています。
追加 (2):
新たに生成されたstateの値を利用するためにmapStateToPropsContainerに追記しています。
追加 (3):
dispatchにToast表示アクションを流し込む設定を追記しています。
まとめ
さて如何でしたでしょうか?
上記実装をすることで連打によるToast表示ができるようになったはずです。
ReactCSSTransitionGroup周りを新たに学ぶ必要があったものの、基本的なReduxのデータフローを理解していればさほど難しくないことがわかったのではないでしょうか。
筆者は結局のところ、Reduxのデータフロー周りで躓くことが多く、不必要に難しく感じてしまっていました。
アニメーションはWebサイト作りにおいて、なくてはならないものなので、これを機にReactでのアニメーション作りの基礎を身に着けたいと思います。
と言ったところで本日はここまで。