こおろぎと蛞蝓

―牛ほどの価値もない

jsx(Reactのほう)に慣れる

この投稿は VirtualDOM Advent Calendar 2014 22日目の記事です。

jsx自体は特に難しいわけではないんだけど、何ができるか詳しくしらなかったので 調べたりしたことを書いていきます。

基本

jsxは、reactのDOM生成部分のsyntax sugarを用意してくれてるイメージ。

Reactで要素を作成するときは

React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')

こんな感じで書くけど、これを

<a href="http://facebook.github.io/react/">Hello!</a>

こんな感じでhtml / xmlライクに書けるようにしてくれるのがjsxの役割。

jsxの構文が実コードでどうなるか知りたい人はここ で見ることができる。

もちろん、コンパイルされたコードみたいに直接Reactを使うことも可能だけど、 Reactがアップデートされたときに提供するAPIの変更があったら辛いことになりそうなので 素直にJSXTransformer使っとくのが良さそう。

jsxコンバータを使おう

jsxで書くのが楽になるのはいいけど、 それでもいきなりReact書く上でjsxの部分を意識する難しい人もいると思う(自分のこと)。

そんな人のため、ありがたいことにjsxコンパータ が用意されている。

Create classのチェックを外すとjsx部分のみの生成ができる。

forhtmlFor, classclassNameに変え忘れるとか最初のうちはよくやりそうなので なれるまではコレを使うの有りだと思う。

ただし、syntaxチェック的なことをしてくれるわけではないので、 元のhtmlが変だと生成されるjsxも変になったりするので気をつけたい。

あと、実体参照を含むhtmlは、jsx Gotchas で言及してるなかの「一番かんたんな方法」でしか変換されないのに注意。

<div>First &middot; Second</div>

<div>First · Second</div>

Spread演算子でkey-valueを展開

下記はエラーになる

var props = {
    className: "myClass",
    defaultValue: "50"
};
var MyComponent = React.createClass({
    render: function() {
        return (
            <input {props} />
        );
    }
});
React.render(
    <MyComponent />,
    document.getElementById('content')
);

単純に{props}みたいにしてもkey-valueが展開されたりしない。

しかし、jsxではSpread演算子(...argsみたいなやつ)がサポートされていて、 下記のような書き方なら正しく動く。

var MyComponent = React.createClass({
    render: function() {
        return (
            <input {...props} />
        );
    }
});

さらに、これはSpread演算子そのままなので上書きもできる

var MyComponent = React.createClass({
    render: function() {
        return (
            <input {...props} defaultValue={"100"} />
        );
    }
});

デフォルト値を用意しておくのに便利。

ついでに、属性を指定するfoo={bar}の書き方は、 barがObjectのときはtoStringされて[object Object]になるが、 style属性の指定に限ってはSpread演算子のときと同様にkey-valueを展開されるので 以下のように書くことができる。

var props = {
    className: "myClass",
    defaultValue: "50",
    style: {
        background: "black",
        color: "white"
    }
};
var MyComponent = React.createClass({
    render: function() {
        return (
            <input {...props} />
        );
    }
});

falsyの扱い

属性ノードに使用するのかテキストノードに使用するのかでfalsyの扱いが全然違うので気をつけたい。

属性ノードのとき

  • 文字列になるのは false, 0
  • 空扱いになるのは ""
  • 設定していない扱いになるのは null, undefined
var mountNode = document.getElementById('content');
React.render(<input value={null} />, mountNode); // valueに設定する値を変えるとわかる

テキストノードのとき

  • どれでもテキストノードは生成されない(文字列になったりはしない)
var mountNode = document.getElementById('content');
React.render(<div>{null}</div>, mountNode);

混乱しそうなので覚えておきたい。

その他

章立てするほどのことじゃないやつ

  • styleを設定するとき、style="width: 100"ってかくと単位が自動的にpxになる
  • jsxコンパータは↑の関係でpxをついたstyle渡しても自動でpx外してくれる(最初バグかと思った)
  • <div className={false ? "hoge" : "fuga"} />みたいに{}の中では三項演算子が使える

おわりに

だいたいのことはDocument に書いてあります。