Reactである配列を元にリストを表示させることは多いかと思います。双方向データバインディングのAngularだと、このリストを簡単に絞り込んだりソートしたりすることができますが、Reactでリストを絞り込んだり、並べ替えたりする場合は、どうすればよいのかということを試してみました。自分なりの実装方法をまとめてみたのでご紹介します。
目次
サンプル
まずはサンプルをご確認ください。keyとvaluを持ったオブジェクトの配列を、入力フォームに入力したワードで絞り込んだり、さらにkeyとvalueを昇順、降順で並び変えたりすることができます。これをReactで実装しています。
JavaScriptで配列の絞り込み機能を実装する
まずはReactで絞り込み機能を実装する方法を説明する前に、一般的なJavaScriptでの絞り込み機能を実装する方法を説明します。
JavaScriptでは配列の要素を絞り込むためのメソッドが用意されています。
array.filter(callback[, thisObject]);
filter()メソッドに指定する引数は以下のようになっています。
- callback
- 返される配列にarrayの要素を含めるかどうかを判断するために呼び出すコールバック関数。callbackは以下の3つの引数で実行されます。
callback(array[i], i, array); - thisObject
- callbackを呼び出す際にthisとして使用するオブジェクトの値(オプション)
filter()メソッドは、配列の各要素に対してcallback関数を1回ずつ実行します。そしてcallback関数がtrue、またはtrueに変換される値を返したarrayのインデックスiの要素だけを元に新たな配列を作成します。新たに作られた配列はfilter()メソッドのreturn値として返されます。
例えば、filter()メソッドを使って、いくつかの数値を含んだ配列から10以上の数字だけを取り込んだ配列を作る場合は以下のようにします。
[参考]
Reactで絞り込み機能を実装する際も、このJavaScriptのfilter()メソッドを使うことになります。
AngularJSで実装すると
ちなみに、Reactでの実装方法を説明する前に、参考としてAnglularJSで絞り込み機能を実装する場合の例を挙げておきます。AnglularJSを使うと以下のようにシンプルに書くことができます。AngularJS側でほとんどの処理が行われるようになっているので、実装は配列を用意するのと、タグにちょっとした属性を付けるだけで済んでしまいます。
AngularJSでは以上のようにとても簡単に絞り込み機能を実装することができますが、Reactではどのように実装していくことになるでしょうか。早速以下よりReactでの実装方法を説明していきます。
Reactで配列の絞り込み機能を実装する
それでは、早速機能の実装について説明していこうと思います。これから先は、ES6の構文で書いていきます。ReactのES6での書き方については、以下を参照してください。
Reactで配列を表示するコンポーネントを作る
絞り込み機能を実装するに当たって、機能を実装するための配列を表示するコンポーネントを作ります。
reactとreact-domを読み込みます。
idとnameを持ったオブジェクトの配列dataを用意し、この後作っていくAppコンポーネントに渡すようにします。
今回の機能の親コンポーネントとなるAppコンポーネントを作ります。上記で渡された配列をpropで受け取り、初期state値として設定します。続いて、そのstateを通して配列をmapして動的にVirtualDOMを作るようにします。
これで用意した配列を表示するコンポーネントは完成です。このコンポーネントに絞り込み機能を実装していきます。
Reactで配列を絞り込む機能を実装する
Appコンポーネント内に配列を絞り込むためのhandleFilterVal()メソッドを実装します。上記で説明したJavaScriptのfilter()メソッドを使ってpropで受け取った配列を絞り込むようにし、絞り込んだ配列(filter()メソッドでreturnされた配列)をsetState()してstateにセットします。
ここでのポイントは、filter()メソッドを実行する配列を、this.state.dataではなくthis.props.dataとすることです。常に完全な配列をチェックさせることで、入力されたキーワードが含まれていない場合、表示を元の配列に戻すような動きを実現させることができるようになります。
絞り込み用の機能を実装したら、次に配列を絞り込むためのキーワードを入力するための入力フォームを実装します。Appコンポーネントに子コンポーネントとしてFormコンポーネントを追加し、上記で定義したhandleFilterVal()メソッドを渡すようにします。
Formコンポーネントを作り、配列を絞り込むためのキーワードを入力するためのフォームを実装します。キーワードを入力するためのinput要素と入力された値を受け取り親コンポーネントから受け取ったhandleFilterValを実行するためのメンバメソッド_filterVal()を用意します。
input要素は、いわゆるReactによって状態を管理されないUncontrolled Componentsとして実装しています。そのため初期値をdefaultValueで指定しています。
Reactで配列を絞り込む機能の実装はこれで完了です。引き続きソート機能を実装する方法を以下より説明していきます。
JavaScriptで配列のソート機能を実装する
まず、Reactでソート機能を実装する方法を説明する前に、一般的なJavaScriptでのソート機能を実装する方法を説明します。
JavaScriptでは配列の要素をソートするためのメソッドが用意されています。
array.sort(compareFunction);
sort()メソッドに指定する引数は以下のようになっています。
- compareFunction
ソート順を指定するための関数を指定します(オプション)。省略した場合は、配列の要素はアルファベット順(文字エンコーディングによって決定される順序)にソートします。配列はその場でソートされ、配列のコピーは作成されません。
compareFunction関数は、2つの引数aとbを取り、以下のいずれかを返させるようにします。
compareFunction(a, b);
- aがbより前に現れるべき場合: compareFunction(a, b)のreturn値は‘0未満の値’
- bがaより前に現れるべき場合: compareFunction(a, b)のreturn値は‘0より大きい値’
- aとbが等しい場合: compareFunction(a, b)のreturn値は‘0’
compareFunction関数は以下のような形式となります。
例えば、sort()メソッドを使って、いくつかのkeyとvalueを含んだオブジェクトを要素にもった配列を、keyのidで昇順にソートする場合と、valueのnameで降順にソートする場合は以下のようにします。
[参考]
Reactで配列のソート機能を実装する
Appコンポーネント内に配列をソートするためのhandleSortByAscend()メソッドとhandleSortByDescend()メソッドを用意し、それぞれ配列を昇順と降順に並び替える機能を定義します。上記で説明したJavaScriptのsort()メソッドを使ってstateに格納されている配列をソートするようにし、ソートした配列をsetState()して再びstateにセットします。
配列の要素はオブジェクトになっているので、それぞれのメソッドの引数にはオブジェクトのkeyをセットするようにし、引数で受け取ったkeyの値をソートできるようにしておきます。それから、絞り込み機能ではthis.props.dataに対してfilter()メソッドを実行しましたが、こちらではthis.state.dataに対してsotr()メソッドを実行するようにしています。配列を絞り込んだ状態でソートできるようにするためです。
ソート用の機能を実装したら、次に配列をソートするためのボタンを実装します。Appコンポーネントに子コンポーネントとしてSortButtonコンポーネントを追加し、上記で定義したhandleSortByAscend()メソッドとhandleSortByDescend()メソッドを渡すようにします。
SortButtonコンポーネントを作り、配列をソートするためのボタンを実装します。昇順、降順に並び替えるためのbutton要素と、それらのボタンがクリックされた際に親コンポーネントから受け取ったhandleSortByAscend()メソッドとhandleSortByDescend()メソッドを実行するためのメンバメソッド_sortByAscend()と_sortByDescend()を用意します。
Appコンポーネント内で定義したhandleSortByAscend()メソッドとhandleSortByDescend()メソッドが何を対象としてソートするか判定できるように、button要素のvalue値に配列のオブジェクトのkeyの値をセットしておきます。
Reactで配列をソートする機能の実装はこれで完了です。
ソースコード
最後にソースを一つにまとめると以下のようになります。
GitHubにもアップしていますので、併せてご確認ください。
まとめ
双方向データバインディングのAngularJSと比べると、Reactでリストの絞り込みやソートの機能を実装するのはだいぶ大変だったりします。ただ、Reactの基本的なデータの流れとそれに伴うUIの実装方法さえ抑えておけば、問題なく実装できるのではないかと思います。実装していて思ったのは、JavaScriptのArrayオブジェクトのfilter()メソッドやsort()メソッドをいかに使うかが肝になってきたりするので、Reactというよりも、この辺りの使い方を覚えておくことも大事なのかなと思いました。
コメント