Code

2017年1月29日日曜日

React Component の Render 関数を変更

 先週、作ってる Web App が別のサイトに入れることになりました。機能としてはそのままですので、JS ファイルをロードすれば ReactDOM.render () 関数を呼び出して、CSS もロードすれば、そのまま Component が動くので、とても便利です。ただ、そのサイトの Analytics 仕組みが今まで使ってるものと違って、<a> や <button> などには data-tracker-type とか、Analytics 専用の属性を追加しなければならない。
 つまり、入れる場所により、render する Component の HTML が少し違います。まぁ、一番思いついた方法はやはり、一つの <a> や、<button> を探し出して、属性を追加するだけです。ですが、これは根本的な解決方法ではありません。なぜなら、開発者にとって負担になるからです。
 本来、プログラミングで解決できる問題は、力でやるのはあまり良くないのです。もう一つの方法としては、property を childContext とか、そのまま各 Component に設定して、render 関数の behaviour をその property を読んで、変更すると。
 property をパスとかいろいろ面倒だから、さらに変更方法を調べてみました。そこで、render 関数を直接変更したほうがもっと簡単だろうと。具体的には、react.createClass(spec) 関数で返された instance には type という実際の Component が含まれています。
 component.type.prototype.render は定義された render 関数です。
 DOM に render する前にその render を変更すれば、そのタイプの Component の HTML も変わります。
 後日また詳細を。それでは。

2017年1月14日土曜日

React.js Component stateless から stateful に変更に伴う問題点

 今週、新しい機能を実装しているうちに、ある Component を Stateless から Stateful に変更しました。その Component を使っているところはあまり変わりがないと思いました。ただ、テストすると、ちょっとだけ不具合が発見しました。
 React.js は Component を更新する際に、もし _owner, key と component の type 変更がなければ、その Component を再利用して、HTML も再利用します。ここで、再利用される Component はもし State を持っている場合、その State は更新されません。もし何か State にある変数を更新したい場合、自分でやるしかないです。ここで、componentWillReceiveProps () 関数が利用して、setState を呼び出して、変数を更新します。
 componentWillReceiveProps では、setState を呼び出しても、実際は一回の Render にまとまります。かなり便利な関数ですね。

 ネットでは、毎回 key を変更すれば、React.js は毎回新しい Component を Mount するので、心配しないで済むとの方法もありましたが、新しい Component を作るにはまたいろいろコストがあるので、前のものを再利用したほうがいいでしょう。

 React.js の中に、Component を更新する方法は setState と新しい Props を渡す、forceUpdate() を呼び出す3種類しかないし、forceUpdate() はあまりおすすめできないし、setProps もないので、setState をうまく使わないといけないです。
 これでまたいつ Component は state を持つべきかとの原点に戻りました。Redux を使うと、store の中に state を置いて、その state と関係あるところは container を通じて、自動的に更新されますが、ただ、それは app 範囲の state の方です。state を持ってる component があまり向いてないようが気がしています。なぜなら、store は個別の component の state を持ってると、もし同じような component 複数ある場合、別の reference を使わないといけません。あるデータをある component のものと示すためです。
 この場合、Wrapper を使ったほうがいいようなが気がしています。state に入れるものは親 Component を持っていて、前の stateless の component も残したほうがいいでしょう。これで、state がいるかどうかによって、使い分けもいいでしょう。とにかく state を持ってない component が再利用しやすいから。ネットでは presentation component という design pattern もあります。こちらは render のみ提供する component と lifecycle 関数や、state を操作する関数を別の component に入れて、container component 両方分けて、どっちでも再利用しやすくするための方法です。
 それでは。