Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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があったら追記していきますので宜しくお願いします。

endam
東京で働くフルスタックエンジニア
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした