React.jsの知っておいて損はないTips

React.jsでの開発を始めてから微妙にハマったポイント、また「これを早めに知っておけばもっとコードを簡潔に書けたのに・・！」という点がいくつかあったので、それらのTipsを共有します。

#renderで返すComponentは単一の親でなければならない
まずは入門編。Reactを始めた人は一度はエラーになったことがあるかも。
renderメソッドで返すのは単一の親のComponentであり、複数の親のComponentを返すことは出来ません。
必ず一つの親になるようにWrapしてあげましょう。

```
// エラーになる
render(){
  return(
    <div>aaa</div>
    <div>bbb</div>
  );
}

// 正常
render(){
  return(
    <div>
      <div>aaa</div>
      <div>bbb</div>
    </div>
  );
}
```

#renderで空を返す
子コンポーネントで親から渡されたデータによって空のComponentを返したい場合があります。
そんな時は空のHTML要素を使わなくてもnullかfalseで返せます。
(ただしundefinedは使えません)

```
render() {
  if (!this.props.isShow) {
    return null; // もしくはreturn false;
  }
  return (
      <div>
        表示します
      </div>
  );
}
```

#JSX内でif/else文の判定やループを行う
条件分岐による要素の変更やループでの要素作成を行う場合、まず変数に代入しておいて、最後のreturn時にJSX内で変数を割り当てる方法があります。

```
render() {
  const label = this.props.isShow ? <div>テスト</div> : null;
  const commentNodes = this.props.data.map((comment) => {
    return (
      <Comment author={comment.author}>
        {comment.text}
      </Comment>
    );
  });
  return (
    <div>
      {label}
      <div className="commentList">
        {commentNodes}
      </div>
    </div>
  );
}
```

または規模がある程度大きい場合子コンポーネントに分割するのを検討します。
しかしごく単純な処理はJSX内でインラインで直接条件分岐やループを書きたい場合もあります。

そこでJSXのインラインで処理する記法が以下になります。

```
render() {
  return (
    <div className="commentList">
      {(() => {
        if (this.props.isShow) {
          return <div>テスト</div>;
        }
      })()}
      {(() => {
        return (
          this.props.data.map((comment)=> {
            return <Comment author={comment.author}>
              {comment.text}
            </Comment>
          })
        );
      })()}
    </div>
  );
}
```

[アロー関数を用いた即時関数](http://analogic.jp/arrow-function/#immediate-function)で処理する方法ですね。
これはReact公式のドキュメントにも記載してあります。
https://facebook.github.io/react/tips/if-else-in-JSX.html

ただこの記事に対するコメントでも指摘があったのですが、即時関数を使う必要は無く、もっと簡潔に書けます。

というわけで↑のコードをLet's修正。

```
render() {
  return (
    <div className="commentList">
      {this.props.isShow && <div>テスト</div>}
      {this.props.data.map((comment)=> {
          return (
            <Comment author={comment.author}>
              {comment.text}
            </Comment>
          );
      })}
    </div>
  );
}
```

うん、見通しが良くなった笑


```
{this.props.isShow && <div>テスト</div>}
```
の部分は三項演算子でも構いません。


```
{this.props.isShow ? <div>テスト</div> : null}
```

ただ全てにおいてインラインで書けば良いというわけではなく、ケースによってコンポーネントの分割やrenderの切り出しを使い分けましょう。
(指摘して頂いた皆さんありがとうございます :pray: )

#onKeyDown/onKeyPress/onKeyUpイベントでのキーコード取得の違い

実はこの３つのイベントの中でonKeyPressだけキーコード取得の方法が違います。
onKeyDown/onKeyUpは引数のイベントのkeyCodeプロパティから取得できますが、onKeyPressでkeyCodeプロパティから取得しようとしても常に0が返ってきます。
onKeyPressでの正しいキーコードの取得はkeyCodeプロパティではなくcharCodeになります。

```
onKeyPress(e) {
  console.log(`onKeyPress KeyCode:${e.charCode}`)
}

onKeyDown(e) {
  console.log(`onKeyDown KeyCode:${e.keyCode}`)
}

onKeyUp(e) {
  console.log(`onKeyUp KeyCode:${e.keyCode}`)
}


render() {
  return (
      <div>
        <form onSubmit={this.onSubmit}>
          <input type="text" onKeyDown={this.onKeyDown} onKeyPress={this.onKeyPress} onKeyUp={this.onKeyUp}/>
          <button type="submit">登録</button>
        </form>
      </div>
  );
}
```

#classNameに文字列と変数を組み合わせて割り当てる
状態によってclass名を割り当てデザインを変更したい場合は往々にあります。

例えば固定のclass名であればダブルクオーテーションでくくります。

```
<div className="header">
```

次に変数を割り当てたい場合は{}でくくります。

```
<div className={showClass}>
```

それでは固定のclass名と変数の組み合わせたい時はどうでしょうか？
間違いがちなのが下の書き方ですね。

```
<div className="header {showClass}">
```

これはエラーになります :no_good:

記法として二つあります。
まずこれも一つの変数に代入してから割り当てる方法

```
const headerClass = "header " + (isShow ? "show" : "hide"); 

...

<div className={headerClass}>
```

二つ目はES6のテンプレートリテラルを使用してインラインで書きます。

```
<div className={`header ${isShow ? "show" : "hide"}`}>
```

僕は二つ目の方法をよく使います。
(個人的にテンプレートリテラルはES6で最も便利な文法の一つだと思ってます :star: )


他に思いついたTipsがあったら追記していきますので宜しくお願いします。