React.createClassで生成したオブジェクトを入れる変数は大文字で始めること
タイトルどおり、凡ミスをしました。
現象と原因
引き続き、React on NW.jsという構成で社内用のツールを作っていたのですが、ちょっとした小さいコンポーネントを追加した際に画面が崩れる(表示されなくなる)という状態になりました。
とても小さいコンポーネントだったので、単純なミスだろうと思いつつもコードを見なおしていたところ、原因は React.createClass()
で生成したコンポーネントを、小文字始まりの変数に入れていたことでした。
実物ではないですが、下記のレベルのコンポーネントで、JSXベースで書いていました。
(function() { var hello = React.createClass({ // <- 変数が小文字始まり render: function() { return ( <h1>Hello, {this.props.name} !</h1> ); } }); React.render( <hello name='React' />, // <- コンポーネントも小文字で指定 document.getElementById('app') ); })();
これを jsx
コマンドでJavaScriptに変換したソースを見たところ、以下のようになっていました。
(function() { var hello = React.createClass({displayName: "hello", render: function() { return ( React.createElement("h1", null, "Hello, ", this.props.name, " !") ); } }); React.render( React.createElement("hello", {name: "React"}), // <- 第1引数が文字列になっている document.getElementById('app') ); })();
これを見ると、 React.render()
内の React.createElement()
で、本来コンポーネントを指定しているはずの第1引数が文字列(上記の例だと "hello"
)になっていて、どうやらこれが原因のもよう。
検証
変数とタグに使っていた hello
を Hello
と大文字始まり書き換えると、想定通りに表示されるようになりました。
(function() { var Hello = React.createClass({ // <- 変数が大文字始まり render: function() { return ( <h1>Hello, {this.props.name} !</h1> ); } }); React.render( <Hello name='React' />, // <- コンポーネントも大文字で指定 document.getElementById('app') ); })();
変換後のJavaScriptを見ても、 React.createElement(Hello, ...)
と、文字列ではなくコンポーネントが指定されていました。
(function() { var Hello = React.createClass({displayName: "Hello", render: function() { return ( React.createElement("h1", null, "Hello, ", this.props.name, " !") ); } }); React.render( React.createElement(Hello, {name: "React"}), // <- 第1引数がコンポーネントになっている document.getElementById('app') ); })();
JSXからの変換を試すことができるサイト でやってみても同じ結果なので、どうやらそういう仕様のよう。
ドキュメントを眺めた限りでは特に触れられていなかったような気がしたのですが、そもそもJSX以前にJavaScriptでクラス的なものを扱うときのルールなどがあるのかも?このあたり、まだまだ勉強不足。
いちおう発生した環境はこんな感じでした。
パッケージ | バージョン |
---|---|
NW.js | 0.12.0-1 |
React | 0.13.1 |
React-tools (jsx) | 0.13.1 |
参考
開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質
- 作者: Cody Lindley,和田祐一郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/06/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る