if文はJSXの中で書け

# はじめに

今日、インターン先オフィスでReactを勉強しているデザイナーさん2人と話していたところ、JSX内の条件文についてまとめ記事があったらいいよねという話になったので淡々とまとめていきたいと思います。簡潔にまとめたいので、前置きはこの辺にして早速始めます。


# そもそもJSXってなに？

JSXとは、**まるでHTMLを書いているかのようにReactを書く**ために作られたものです。なので

```jsx
    return (
        <div>
            <h1>僕のホームページ</h1>
        </div>
    )
```

詳しいことは割愛しますが、この**`return()`内のタグは実際にはHTMLのタグではないです。**

`return()`内に来るのはHTMLのコードではなくJSXなので、たとえば

```jsx

    const hoge = 'fuga'

    return (
        <div>
            <p>{hoge}</p>
        </div>
    )
```

このように{}で囲むことによって、JSX内に直接`JavaScript`で定義した変数や定数（なんなら返り値のある関数でも）つっこむことができます。
その結果、上のコードから実際には

```html

<div>
    <p>fuga</p>
</div>
```

というHTMLタグが生成されることになります。


# 本題：if文はJSXの中で書け

ReactでWeb開発をする際、次のような実装をする場面が出てくると思われます。

**`props`にて`icon`が定義されている場合のみ、ラベルとともにアイコンも表示するようなボタンを実装したい**

普通のif文しか知らなかった頃の僕は、このような書き方をしていました。（お恥ずかしい、、笑）

```jsx

    const HogeComponent = ({ icon, label }) => {  // propsはこのように{}で囲んだ中に直接定義することもできる

        if (icon === undefined) {  // iconが渡されていない場合
            return (
                <button>
                    {label}
                </button>
            )
        } else {
            return (
                <button>
                    {icon}
                    {label}
                </button>
            )
        }
    }
```

これ、iconを表示するかしないかだけの違いなのに同じことを2回書いてしまっています。

では、if文をJSXの中で書いてみましょう。

```jsx
    const HogeComponent = ({ icon, label }) => {

        return (
            <button>
                {icon && <img src={icon} alt='icon' />}
                {label}
            </button>
        )
    }
```

随分とすっきり書けました。
なぜこのように書けるのか少し掘り下げてみましょう。

```jsx
   {icon && <img src={icon} alt='icon' />}
```

ここに注目します。
これこそがJSX内のif文（正確にいうと条件式）で、iconは左辺、&&の後は右辺と呼ばれます。
この文は、**左辺（つまり条件部分）が`true`であるときは右辺を、そうでないときは左辺を**返します。
`icon`の中身は、

- 定義されている時・・・画像データ
- 定義されていない時・・・`undefined`

でした。
つまりアイコンが定義されているときは`<img />`タグ、定義されていない場合は`undefined`が返されています。
ここからが重要です。
**JSX内で`undefined`や`false`、`true`、`null`などが返された場合、Reactはそれらを完全に無視します。**
つまりは何もレンダー（描画）しません。

ここに関して、僕は長い間勘違いをしていました。上の条件式について、単純に条件おいて&&の後に描画したいコンポーネントおけばいいんでしょ？くらいにしか思っていませんでした。そのため、条件の部分には`true`か`false`をとるものしか置いてきませんでした。

このような内部的な動きに関しても理解を深めておくことはとても重要なんだなと改めて認識した出来事でした。

## 左辺を返り値にしたくない場合

条件を満たさない場合でも左辺を返り値にしてしまいたくないとき、次のような書き方ができます。

```jsx

    const HogeButton = ({ primary, label }) => {

        return (
            <button>
                {primary
                    ? <div className='primaryButtonInner'>{label}</div>
                    : <div className='normalButtonInner'>{label}</div>
                }
            </button>
        )
    }
```

ボタンが`primary`なのかどうかを`true`か`false`で渡されて、それに応じてボタンのインナーのスタイルを変えたいという場面です。
これは三項演算子と言います。primaryが真のとき?以降が、そうでないとき:以降が返されます。


**（2020/10/2更新）**

@thomasJs8 さんよりコメントをいただきました。

下の補足にもありますが、三項演算子は様々なところで使えるのでこのようにも書けます。

```jsx

    const HogeButton = ({ primary, label }) => {

        return (
            <button>
                <div className={ primary ? 'primaryButtonInner' : 'normalButtonInner' }>{label}</div>
            </button>
        )
    }
```

条件分岐による影響範囲の大小により、どの範囲に三項演算子を適用するか都度考えて実装すると無駄のない綺麗なコードを書くことができます。

今回の内容には直接関係のない補足ですが、

```js

const HogeFunction = ({ active }) => {

    const result = (active) ? 'hoge' : 'fuga'
    return result
}
```

三項演算子は上のようにJSX内以外でも使えます。（当たり前ですが）
この場合`active === true`のとき文字列hogeが、`active === false`のとき文字列fugaが返されます。
この書き方のいいところは、

```js
const HogeFunction = ({ active }) => {

    if (active) {
        const result = 'hoge'
    } else {
        const result = 'fuga'
    }

    return result  // undefined
}
```

このような**スコープの違いにより実現できないコード**を解決してくれることです。
それぞれの`result`は{}で囲まれている、つまり、それぞれ閉鎖的なスコープに閉じ込められているため、スコープの外からは見えません。
そのため、`HogeFunction`は`active`の値と関係なく`undefined`を返します。


**（2020/10/2更新）**

ここに関しても、@thomasJs8 さんよりコメントをいただきました。

ここで宣言している定数`result`を`return`するわけではない時は三項演算子を使うのが賢明ですが、`return`してしまいたい時

```js
const HogeFunction = ({ active }) => {

    if (active) {
        return 'hoge'
    } else {
        return 'fuga'
    }
}
```

とif文内で`return`することもできます。



# 最後に

今回紹介した書き方は、わりと既に広く使われているものだと思います。しかし、内部的にどのように動いているのか深く掘り下げて考えてみることに価値があると思い、まとめて投稿してみました。この記事が皆さんのReactに対する深い理解の一助になれば幸いです。

# 参考リンク

- 条件付きレンダー

https://ja.reactjs.org/docs/conditional-rendering.html

- JSXを深く理解する

https://ja.reactjs.org/docs/jsx-in-depth.html