LoginSignup
516

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-09-20

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>
  );
}

アロー関数を用いた即時関数で処理する方法ですね。
これは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イベントでのキーコード取得の違い

実はこの3つのイベントの中で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があったら追記していきますので宜しくお願いします。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
516