react-style-guideの日本語訳が見つからなかったので、ざっと読むだけでなく英語の勉強がてらオレオレな和訳をしてみた。(半分ぐらい個人用メモ状態です)
(わからない部分はGoogle翻訳に頼ったし諦めたりしたりしたし)ものすごい誤訳意訳口語訳多数だと思うので、指摘等いただけると幸いです。
Reactの"独特な"考え方は今までこれといってスッキリと書くことができなかった。
だから私は、所属するチームで過去数ヶ月の間で使ってみたイケてる感じのReactの書き方についてまとめてみようと考えた。
この記事は、React-Componentsに限定した範囲での話をします。
(JavaScriptの)プログラミング全体のスタイルや、componentization(Web Componentsを用いた開発?)、Fluxの概念とかの話ではないです。
同様に、ドキュメントは生きていますし、これより良いReactの書き方は有ると思いますので、ぜひフィードバックしてね :)
##構造論
-Method Organization
だいたいこんな感じの種類のライフサイクルメソッドを使います
(この順番で書きます)
React.createClass({
displayName : '',
propTypes: {},
mixins : [],
getInitialState : function() {},
componentWillMount : function() {},
componentWillUnmount : function() {},
render : function() {}
});
displayNameは開発中にデバッグするのが楽になるので設定しといたほうがいいよ!
あと私は一番上に置くのが好みで、propTypesとmixinsをその次に書くよ。
PropTypeはpropsの入力値のバリデーションチェックに加えて、あなたがこのコンポーネントをどんな感じに使って欲しいか、という明確なドキュメントを書くときに特に使えるよ!
もしあなたがコンポーネント内で関数(function)をカスタマイズしたかったら、私はそれを(ReactのAPIと)区別するために頭にアンダースコアをつけることを好みます。
で、render functionの上に書きます。
React.createClass({
displayName : '',
propTypes: {},
mixins : [],
getInitialState : function() {},
componentWillMount : function() {},
componentWillUnmount : function() {},
_onChange : function() {},
_onCreate : function() {},
render : function() {}
});
render functionより下のほうに書くべきかとも考えたんだけど、現実的に考えるとComponentを一番下までスクロールしたときにはrender functionがいつでも一番下に来ていることがわかっていた方がいいよね。
同じように、私は出来る限りすべてのコンポーネントのJSXはrenderの中に書かれていることを好みます。
##条件付きのHTML
Conditional HTML
(繰り返すことに価値がある ?)
JSXでは、HTMLの中の{}の中身はなんでもJavaScriptに評価されることに価値があります。
なので、あなたがなんかシンプルな条件文をrenderしたいと思ったら、あなたは同じHTMLの中で三項演算子(ternaries)を使えばいいです。
{this.state.show && 'This is Shown'}
{this.state.on ? ‘On’ : ‘Off’}
(HTMLを作るときに)もっと複雑なものについては、suffix(末尾)にHtmlとつけて変数として書いておいて、render関数内では変数として展開します。
var dinosaurHtml = '';
if (this.state.showDinosaurs) {
dinosaurHtml = (
<section>
<DinosaurTable />
<DinosaurPager />
</section>
);
}
return (
<div>
...
{dinosaurHtml}
...
</div>
);
##返り値や変数としてのJSX
JSX as a Variable or Return Value
JSXで複数行になる場合は
こんな感じで(括弧で)ラップして挿入します
var multilineJsx = (
<header>
<Logo />
<Nav />
</header>
);
一行だったらこんな感じで挿入します(括弧つけないって意味だと思う)
var singleLineJsx = <h1>Simple JSX</h1>;
しかし、(一行だと)複雑な感じだったり、今後拡張されそうな場合とかは(括弧で)ラップします。可読性と利便性のために。
##閉じタグ
Self-Closing Tags
子要素の無いコンポーネントは↑で出したLogoをみたいな感じで自分のタグの中で閉じます。
<Logo />
↓みたいに不必要にタグを分けないように
<Logo></Logo>
##Listのイテレーション
List Iterations
私はlistのイテレーションはdinosaurHtmlであげたような感じで使います。
特にそれぞれのlist itemをコンポーネントとしてレンダリングしない限り、listのイテレーションは(HTMLの)インラインに書いたほうが良いことがわかったんです。
あなたは長くなった1行を減らしたくなるかもしれないけどね。
render : function() {
return (
<ul>
{this.state.dinosaursList.map(dinosaur => <DinosaurItem item={dinosaur} />)}
</ul>
);
}
JSXのharmony flagが必要です。
アロー関数(fat arrow)とかテンプレートリテラル(template strings)とか分割代入(Destructuring assignment)とかレストパラメータとかその辺を使うために。
http://kangax.github.io/compat-table/es6/#jsx に列挙されてます。
JSXをわざわざコンパイルしているんなら、ES6の機能も使えるから、JSXのharmony flagとかbabel的なものとかを使ったほうがいいよ(私らはbabelを使ってます)
##フォーム
Forms
フォームのstateをコンポーネントの内部とか、例えばFluxのStoreとか外部に保存しておくために、ReactのAddonsのLinkedStateMininを使うとか、自分でhandler(s)を書いておくべきだ。
LinkedStateMixinを使うのは、ここのドキュメントをみるとめっちゃ簡単に使えます。
もしFluxのstoreのハンドラを使うんだったら、↓みたいな感じで1つの抽象的に書くことができて、それぞれのフィールドに運ぶことができます。
<input type="text" value={this.state.newDinosaurName} onChange={this.inputHandler.bind(this, 'newDinosaurName')} />
inputHandlerはこんな感じ
function(fieldName, event) {
actions.propagateValue({
field : fieldName,
value : event.target.value
});
}
Hacker Newsスレッドで@insinが書いていた更にいいパターンが、すべてのinput formでonChangeハンドラを置かずに、以下のようにほんとに必要なハンドラを1つだけ置いている
<form onChange={this.inputHandler}>
...
<input type="text" name="newDinosaurName" value={this.state.newDinosaurName} />
...
</form>
そのときのinputHanderはこんな感じ
function(event) {
actions.propagateValue({
field : event.target.name,
value : event.target.value
});
}
※訂正:
この記事ではコントロール出来ないフォームフィールドが〜
直接Stateでコントロールできるようなフォームフィールドのほうが好ましいと書いてあった。
この意見は修飾されていないものだった(?)
私はそれがフォームフィールドとStateの値が一致する
と無駄なDOMアクセスを避けるために有益だと思った。
##フォーマットの整え方
Formatting Attributes
下みたいな長いinput formでは、綺麗で簡単に見えるように改行しましょう
<input
type="text"
value={this.state.newDinosaurName}
onChange={this.inputHandler.bind(this,
'newDinosaurName')} />
対照的に、タグで整列させるのも、どちらもインデントがないものよりかは読みやすいと思うけど、↑よりもちょっと読むのが大変かも
<input type="text"
value={this.state.newDinosaurName}
onChange={this.inputHandler.bind(this,
'newDinosaurName')} />
##終わりに
Closing
今回、我々がReactを書いている中で使えそうだと思ったパターンをほんの少し紹介しましたが、決して"こうすべきだ!"と強制するものではありません。
もし、反対なアイデアとかあったらコメント欄とかでお申し出ください。
(ベストプラクティス的な)この種の議論はReactのエコシステム全体に対してとても有益なものになるでしょう。
私はぜひともaddress stylingとかcomponentization(minixsの使いドコロとか、propsとstateの使い分け方とか会話方法?とか)とか、Fluxについて書いてあるstyle guideを読んでみたいです
よんでくれてありがとー