Next.js Tutorial -- header 部分の分岐 -- 三項演算子と && と ||
前提
これの条件分岐で苦戦したのでメモを残しておく
ヘッダーの大きさとリンクの有無を可変にする
<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 の見栄えとコード
画像
一部省略。実際の見栄えは次の画像のようになる
アイコンの画像と文字が大きく、二つともリンクになっていない
説明
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 では
こうなる
説明
アイコンの画像と文字が小さく、二つとも root へのリンクになっている
同じ
コード
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 - 非数
|| とは -- Logical Or
考え方は同じで
If expr1 can be converted to true, returns expr1; else, returns expr2.
なので
A || B || C
だったら
A が truethy だったら A を返す
でなければ B を返す。しかしここでは B 相当が ( B || C ) になるので ...
と
最初に見つかった Truethy の値を返し、全て Falsy なら 最後の値を返す
式になる。
以上。