Code

2016年7月24日日曜日

React.js re-render で State のクリア方法

 通常 React.js を使うと、コンポーネットを作って、DOM に render したら、たまには props を渡して、元の状態でもう一度 render したい時があります。ただ、state はコンポーネントを保持しているので、props が変更するだけで、re-render をしても、state が最初に戻らないのです。なぜなら、コンポーネントの getInitialState はコンポーネント最初の一回のみ実行されて、unmount を実行して、再 render しない限り、state は前の状態に保持されます。
 内部の操作としては、props が変更したら、React.js はコンポーネントを DOM から消して、もう一度作るではなく、変更した部分だけ再度 render するだけです。同時に、ライフサイクルの関数を見てみると、 componentDidMount は一回だけ呼び出されて、そのあとは全て、componentDidUpdate が呼び出されます。
 じゃ、どうやって、props 変更する際に state もクリアしますかと。基本的に二つ方法があります。
 まずは、componentWillReceiveProps () 関数が毎回新しい props が渡されるとき呼び出されますので、その中で props に応じて、setState を呼び出して、リセットします。  それに、この関数の中で setState で state を変更しても、re-render が起こらないです。props の変更と state の変更が一回の re-render で更新されます。他のところで、 setState を呼び出すと、shouldcomponentUpdate から render、componentDidUpdate まで一通り実行されます。これは最善策です。
 具体的に、getInitialState () で prepareInitialState を使って、新しい object を返します。親が re-render して、props が渡されたら、componentWillReceiveProps () 関数の中で、条件を判断して、もし state をクリアしたい場合、setState (prepareInitialState()) を呼び出すと、state が最初の状態に戻されます、props の変更とともに。
 もう一つの方法は props と一緒に key を変更する。key をコンポーネントに設定すると、React.js の Virtual DOM 比較アウルゴリスムはコンポーネントのタイプ、key などの属性を最初に比較します。key が変更したことは、別のコンポーネントになるわけです。
 ネットでは key を new Date() を設定して、親からの re-render があれば、変更されますので、いつもコンポーネントを最初から re-render します。

 個人的には、方法1を使うべきです。React.js はすでに componentWillReceiveProps() 関数が提供されたので、それを使うべきです。方法2としては、確かに同じ目的が達成できるかもしれないが、実行されるコードが多いのです。それに、本来なら、re-render 必要ないかもしれないサイクルでも、key が変更されて、re-render になります。全体的に複雑になります。

 それでは。

2016年7月9日土曜日

iOS 9 HTML5 モーダル スクロールできない問題

TL; DR: iOS で modal を表示しても、body が相変わらずスクロールできるの修正方法:modal-open クラスに positive: relative を追加すれば、修正されます。
 Bootstrap などを使うと、簡単に Modal ウィンドウが作れるようになります。基本的に CSS もあって、関数を呼び出すだけです。そのモーダルウィンドウは一般的に画面の真ん中に、スクロールできないようになっています。これは modal-open というクラスを body tag に設定することで、body の overflow を hidden に設定するだけでできています。
 そうすると、モーダルウィンドウ自身はスクロールできるし、いつも画面の真ん中にあります。ユーザーに操作を提示しているため、最適していると思います。
 iOS 9 がリリースされて、一つの問題は発生しました。body のスクロール禁止が効かなくなりました。
 対応方法としては
    modal-open { overflow: hidden; position: relative; }
 にして、元と同じように動きます。PC ではこの問題が起きません。

 他の修正方法としては、html, body と一緒に overflow: hidden を設定します。

 それでは。