大学生からの Web 開発

会社の人に見つかってぽよぽよしてきた

React 触った

Web 開発での Reactive programming の潮流に乗れていなかったことに危機感を覚えて、その界隈で最も有名な JS ライブラリ React を触った。以降、v0.12.2 での話。

やったのは、公式チュートリアルと一人React.js Advent Calendar 2014を10日目まで読んだこと。

これも読んだほうがいい。

成果はこちら。

上のはTutorial そのまんまの内容で、下のはこういうカウンターを作っただけ。でも意外と詰まった。

f:id:karur4n:20150303163015g:plain

感想

MVC でいう V だけを扱うライブラリなので、やることは多くなくて触りやすい。React.createClass で Component を定義して、React.renderレンダリング。Component 間は props っていうプロパティ群のオブジェクトを用いてやりとりする。これが基本。

感想書こうと思ってもこれまで JS を追いかけられていないので、何かと比較してどうかって書けない。Component でノードの親子関係やイベントを管理しやすくなってうれしい、って感じ。

あと、Component のタグに onClick とかを書いていくことや、コードのロジック内にマークアップすることってどうなんだろうと思ったけど、それはこれを読んでスッキリ納得した。

「関心の分離(Separation of concerns)」ではなくて「技術の分離(Separation of technologies)」だとしていて、マークアップとViewのロジックは密であるべきとしています。

reactjs - React.jsのComponentについて - Qiita

ただ良さげなテンプレートが出たらそれを使いそうな気はする。

詰まったとこ

Counter を作る際に詰まった。カウントされる値をどこで持つかだ。

f:id:karur4n:20150303163015g:plain

当初は、こういう構成にしていた。

  • Counter
    • CountNum (カウント値を表示する Component)
    • CountForm (Up, Down させるボタンの Component)

React は値やイベントのやりとりは親と子で行い、隣接する Component とは直接にはできないっぽい。 CountFormonClick を受けて、Counter のイベントを発火させて Counter から CountNum のイベントを発火させて CountNumstate を変化させる、っていう多重がだるかった。

結局、めんどくさくなって 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 にしようとしてちょっとつまづいた。CountFormthis.props.count の値と Counterthis.state.count の値が異なるのだ。Up, Down するにしても this.props.count の値が期待のものより ±1 違った。

CountFormcomponentWillReceiveProps を使うことで解決した。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 を触るようになってきた。もともとそれらについて多かれ少なかれ知識はあるので、進行にはついていけているのだけど、自分で少し拡張を加えようとしてハマったのでメモ。

f:id:karur4n:20141008191452j:plain

授業内容

以下のようなコードを書いた。各 イメージは 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%;
}

こんな感じ。 f:id:karur4n:20141008191825p:plain

そして、並べられたサムネイルをクリックすると#bigImg がクリックした画像になってビジブルになるスクリプトを書いた。書いたんだけど、これが #bigImgを表示したあとはそのままで、リロードしないと表示が切り替わらないというものだった。また、img タグにonClick="displayImg('1.jpg')" と記述してあったことも気になった(onClick にはいろいろあるけど、なんか気持ち悪いので書きたくないなと思った)。

それでなんとか授業中に、JS だけでイベントを管理して、かつ#bigImgがビジブルの状態で再度クリックすると消えてくれるものを書こうとした。

書けなかった。

家に帰ってやってみるとできた。

できた

授業中に考えていたアプローチはこうだ。

  • クリックされた時に document.onclick を発火させて #bigImg を隠す
  • さらにそのクリックが thumbnail に対するものならば、 #bigImgsrcを変更して、可視化

出来なくはないだろうけど、わざわざややこしく考えていた。これだけでよかったんだ。

  • クリックされたものがサムネイルなら#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';
  }
}

もっと良い方法があれば教えてほしい。

なんてことない簡単なものだったのにできなかったことが悔しい。