React 触った
Web 開発での Reactive programming の潮流に乗れていなかったことに危機感を覚えて、その界隈で最も有名な JS ライブラリ React を触った。以降、v0.12.2
での話。
やったのは、公式チュートリアルと一人React.js Advent Calendar 2014を10日目まで読んだこと。
これも読んだほうがいい。
成果はこちら。
上のはTutorial そのまんまの内容で、下のはこういうカウンターを作っただけ。でも意外と詰まった。
感想
MVC でいう V だけを扱うライブラリなので、やることは多くなくて触りやすい。React.createClass
で Component を定義して、React.render
でレンダリング。Component 間は props
っていうプロパティ群のオブジェクトを用いてやりとりする。これが基本。
感想書こうと思ってもこれまで JS を追いかけられていないので、何かと比較してどうかって書けない。Component でノードの親子関係やイベントを管理しやすくなってうれしい、って感じ。
あと、Component のタグに onClick とかを書いていくことや、コードのロジック内にマークアップすることってどうなんだろうと思ったけど、それはこれを読んでスッキリ納得した。
「関心の分離(Separation of concerns)」ではなくて「技術の分離(Separation of technologies)」だとしていて、マークアップとViewのロジックは密であるべきとしています。
ただ良さげなテンプレートが出たらそれを使いそうな気はする。
詰まったとこ
Counter を作る際に詰まった。カウントされる値をどこで持つかだ。
当初は、こういう構成にしていた。
CounterCountNum (カウント値を表示する Component)CountForm (Up, Down させるボタンの Component)
React は値やイベントのやりとりは親と子で行い、隣接する Component とは直接にはできないっぽい。
CountForm
で onClick
を受けて、Counter
のイベントを発火させて Counter
から CountNum
のイベントを発火させて CountNum
の state
を変化させる、っていう多重がだるかった。
結局、めんどくさくなって Counter
Component で count を表示することにした。
【追記】
何にもつらくなった。
Counter で state.count を持って、それを CountNum, CountForm に配って、それらの子 Component は componentWillReceiveProps
で受ければいいだけだった。componentWillReceiveProps
については以下で書いてる。
【追記終わり】
あと、もうひとつ。
var Counter = React.createClass({ getInitialState: function() { return {count: 0}; }, addable: function() { n > 0 || (n < 0 && this.state.count > 0) }, changeCount: function(n) { if (this.addable) { this.setState({count: this.state.count + n}); } }, render: function() { return ( <div className="counter"> {this.state.count} <CountForm count={this.state.count} handleCount={this.changeCount} /> </div> ); } });
Counter
の値が 0 以下なら、Down ボタンを disabled にしようとしてちょっとつまづいた。CountForm
の this.props.count
の値と Counter
の this.state.count
の値が異なるのだ。Up, Down するにしても this.props.count
の値が期待のものより ±1 違った。
CountForm
で componentWillReceiveProps
を使うことで解決した。state に依存した props をやりとりするときは、componentWillReceiveProps(nextProps)
で新しい props を取得できる。
Updating: componentWillReceiveProps - Component Specs and Lifecycle | React
うまく説明できていないのは、React に対する自信がないから。
勉強する動機
モバイル環境でネイティブ並みの速度が出ればうれしい。Web 開発の手軽さでアプリを作りたい。
前線に走らないといけない
僕は、2013年〜2014 年の JS 界隈が Backbone とか AngularJS に代表される MVC フレームワークで盛り上がっていた様子をやるやる詐欺で外部から見ていた人間なんだけど、今回の React の潮流もそれに見えて、「結局それらを使うことで自身の問題解決につながっている人は少ない、今回の React もまだ使う必要ないんじゃないか」と思っていた。
でも、それは間違いかもしれない。その時代の前線を走ることで、「後発で出たこのライブラリは、過去の辛かったこういう部分が解決されたものなんだ。」と文法のみにとどまらない知識が身につき、理解を深める。前線を築いていくことは、自分をプロのエンジニアに押し上げてくれる。うーん、励みたい。
今日のヤックシェービング
今日のヤックシェービング
- Bourbon, Neat, Bitters っていう CSS ライブラリが良さげ
- 試そう
- フロントエンドライブラリは bowerで 入れよう
- あれ bower 入ってない
- そういやこの前、node.js のバージョンを新調したんだった
npm install bower -g
- さあ css ライブラリ入れるぞ
- bower で導入するとめっちゃパス長い これどうしたらいいねん
- gulp 使っていいことしたい
gulpfile.coffee
の書き方どうだっけmain-bower-files
が bower のパス周りを良くしてくれるのか?- これ css に使えないやつだ
- いいや 長いパス書いて import しよう
gulp-ruby-sass
を入れる- なんかそれより
gulp-sass
の方が流行ってる - gulp-sass コンパイルできねえ なんでだ
- 知らずに unstable の node.js を使っていたため
- unstable って知らなかったわ
v0.10.35
を入れる - qiita に書こ
- emoji cheat sheet 見る
- 書いた
- アイスと最近飲むようになった缶コーヒーを口に入れる
- だらだら探索
- bower は JS のためのもの感がする
- component っていうやつは HTML, CSS, JS をすべてまかなうつもりのパッケージマネージャらしい
- ググラビリティの低さをめっちゃ叩かれてる……
- component に bourbon とかなかったからいいやって投げる
- bower, gulp に戻ろう
- gulp-sass でコンパイルするぞー
- エラー……?
- bourbon のリポジトリに エラーメッセージ に該当する issue あった
- もういいや これ直ってからしよう
- とりあえず github の sandbox の方に push しとこう
git add .
- わーわー いらないファイルめっちゃ入った
- gibo 使おう
git add .
- bower_components 入った
- gibo って bower ないのか
- gi ってやつならある
- まあ gibo でいいか
- push
普段から、気になる技術への素振りをしておく必要性を強く感じた。
解けなかった JavaScript のクリックイベント
授業で HTML, CSS, JavaScript を触るようになってきた。もともとそれらについて多かれ少なかれ知識はあるので、進行にはついていけているのだけど、自分で少し拡張を加えようとしてハマったのでメモ。
授業内容
以下のようなコードを書いた。各 イメージは 1600x1200 くらいととても大きなもの。position: absolute
の見えない画像がページ左上に配置してある。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>サンプル</title> <link rel="stylesheet" href="./style.css"> </head> <body> <img src="img/1.jpg" id="bigImg"> <div> <img src="img/1.jpg" class="thumbnail"> <img src="img/2.jpg" class="thumbnail"> <img src="img/3.jpg" class="thumbnail"> <img src="img/4.jpg" class="thumbnail"> </div> <script src="./app.js"></script> </body> </html>
.thumbnail { width: 300px; } #bigImg { visibility: hidden; position: absolute; top: 0; width: 100%; }
こんな感じ。
そして、並べられたサムネイルをクリックすると#bigImg
がクリックした画像になってビジブルになるスクリプトを書いた。書いたんだけど、これが #bigImg
を表示したあとはそのままで、リロードしないと表示が切り替わらないというものだった。また、img タグにonClick="displayImg('1.jpg')"
と記述してあったことも気になった(onClick にはいろいろあるけど、なんか気持ち悪いので書きたくないなと思った)。
それでなんとか授業中に、JS だけでイベントを管理して、かつ#bigImg
がビジブルの状態で再度クリックすると消えてくれるものを書こうとした。
書けなかった。
家に帰ってやってみるとできた。
できた
授業中に考えていたアプローチはこうだ。
- クリックされた時に
document.onclick
を発火させて#bigImg
を隠す - さらにそのクリックが
thumbnail
に対するものならば、#bigImg
のsrc
を変更して、可視化
出来なくはないだろうけど、わざわざややこしく考えていた。これだけでよかったんだ。
- クリックされたものがサムネイルなら
#bigImg
のソースを変更して、表示する - クリックされたものがサムネイルでないなら
#bigImg
を隠す
var bigImg = document.getElementById('bigImg'); document.onclick = function (event) { if (event.target.className == 'thumbnail') { bigImg.src = event.target.src; bigImg.style.visibility = 'visible'; } else { bigImg.style.visibility = 'hidden'; } }
もっと良い方法があれば教えてほしい。
なんてことない簡単なものだったのにできなかったことが悔しい。