KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

Next.js Tutorial -- header 部分の分岐 -- 三項演算子と && と ||

前提

nextjs.org

これの条件分岐で苦戦したのでメモを残しておく

ヘッダーの大きさとリンクの有無を可変にする

      <header className={styles.header}>
        {home ? (
          <>
            <img
              src="/images/profile.png"
              className={`${styles.headerHomeImage} ${utilStyles.borderCircle}`}
              alt={name}
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <a>
                <img
                  src="/images/profile.png"
                  className={`${styles.headerImage} ${utilStyles.borderCircle}`}
                  alt={name}
                />
              </a>
            </Link>
            <h2 className={utilStyles.headingLg}>
              <Link href="/">
                <a className={utilStyles.colorInherit}>{name}</a>
              </Link>
            </h2>
          </>
        )}
      </header>

この部分。

home あり

home がある場合、 で描画された場合は

home ? A : B の A 部分の処理になり

リンクなしで profile image を描画、8 x 8 rem で 円形に装飾。

リンクなしで 2XL で profile の名前を表示

home なし

home がない場合、 で描画された場合は

B 部分の処理になり

root へのリンクをつけて profile image を描画、6 x 6 rem で 円形で描画

root へのリンクをつけて profile name を Large サイズで描画

まとめ

ホーム画面では

自分の画像が大きくなり、クリックしても root にリンクされない。

また自分の名前が大きくなり、クリックしても root にリンクされない。

一方他の画面では

自分の画像が小さくなり、クリックすると root にリンクされる。

また自分の名前が小さくなり、クリックしても root にリンクされる。

home がない場合にはホームへのリンクを表示する

      <main>{children}</main>
      {!home && (
        <div className={styles.backToHome}>
          <Link href="/">
            <a>← Back to home</a>
          </Link>
        </div>
      )}

main の下がこうなる。

装飾を省略して書くと

{ !home && (
  <div> back to home <div/>
}

になる

意味がわからなかったが、

三項演算子の処理の別の書き方らしい

{(
  home
    ? false
    : <div>back to home</div>
)}

三項演算子だとこうなるらしい

home がある場合は 描画が false になって、ない場合に div が出る。

同じ動作をするのを確認した。

jsx は

if での条件分岐 > 三項演算子での条件分岐 > && 構文での省略分岐

の順で簡単にかけるようだ。

動作確認

Layout のコード

Layout はこのコードを使っている

export default function Layout({children, home}) {
  return (
    <div className={styles.container}>
      <Head>
      </Head>

      <header>
        {home? (
          <>
            <img 
              src='/images/profile.jpeg'
            />
            <h1 className={utilStyles.heading2Xl}>
              {name}
            </h1>
          </>
        ) : (
          <div>this is not home</div>
        )}
      </header>

      <main>
        {children}
      </main>

      {!home && (
          <Link href="/">
            <a>← Back to home</a>
          </Link>
      )}
    </div>
  )
}

index の見栄えとコード

画像

一部省略。実際の見栄えは次の画像のようになる

f:id:kei_s_lifehack:20210121093047p:plain

アイコンの画像と文字が大きく、二つともリンクになっていない

説明

index ( root ) POSTS LIST

pages/index.js

home を渡しているので文字が大きく、

画像と文字にリンクがなく(画像ではわかりにくいが)

home へのリンクの誘導のところが表示されていない

コード

index のコードはこう

export default function Home( { allPostsData } ) {
  return (
    <Layout home>
      <Head>
        <title>posts list</title>
      </Head>
      <h1>
        POSTS LIST
      </h1>
      {
        allPostsData.map( ( { id, date, title, } ) => (
          <h2 key={id}>
            title: {title}
            <br/>
            id: {id}
            <br/>
            date: {date}
            <br/>
            contents: {}
          </h2>
      ))
      }
    </Layout>
  )
}

Layout に home を渡している

詳細ページ の見栄えとコード

画像

詳細ページとして簡易的に一時的に作っている pages/posts/first-post.js では

f:id:kei_s_lifehack:20210121093249p:plain

こうなる

説明

アイコンの画像と文字が小さく、二つとも root へのリンクになっている

同じ を使っているが、詳細 では home を渡していないのでこうなる。

コード

first-post.js のコードはこう

export default function FirstPost() {
  return (
    <Layout>
      <Head>
        <title>
          First Post
        </title>
      </Head>
      <h1>
        Temporary Post Detail Page
      </h1>
      <h2>first post ....</h2>
    </Layout>
  )
}

JS の「式」について

A && B は TF を返す And ではなくどちらかを返す Logical And である

A && B は 「A であり B」だと思っていたが、

JS の場合は全く違った。 falsy を探し出す式だった。

MDN によると

expr1 && expr2

expr1 を false と見ることができる場合は、expr1 を返します。そうでない場合は、expr2 を返します。

という計算だった。全く AND ではない。falsey がどこにあるかの判定でしかない。

A && B && C && D && ..

と判定を続ける場合、

A と B を比較して Falsy か確かめる。A が falsy なら A を返す

違う場合は B を返すが、 B 相当のものがここでは

A && B

A && (B && C && D &&...)

となっているので B を返すために B && C 以降の計算を続ける

ここで B が Falsy であれば B を返して計算終了。

違う場合は C を返すが、C 相当が ( C && D &&...) になっているので以降の計算を繰り返す。

つまり最初に見つかった Falsy の値を返すか、Falsy がなければ 最後の値を返す式になっている。

Falsy とは -- false を含むマイナスっぽいもの

なお Falsy はこれ

false    false キーワード
0   数値ゼロ
-0  数値マイナスゼロ
0n  BigInt で、論理値として使用された場合、 Number と同じ規則に従います。 0n は偽値です。
""  
空文字列の値

null    null - 何も値が存在しないこと
undefined   undefined - プリミティブ値
NaN NaN - 非数

developer.mozilla.org

|| とは -- Logical Or

developer.mozilla.org

考え方は同じで

If expr1 can be converted to true, returns expr1; else, returns expr2.

なので

A || B || C

だったら

A が truethy だったら A を返す

でなければ B を返す。しかしここでは B 相当が ( B || C ) になるので ...

最初に見つかった Truethy の値を返し、全て Falsy なら 最後の値を返す

式になる。

以上。