〜toPropValueの解説〜Tweetこんにちは!りょた(@Ryo54388667)といいます(^o^)今回はNext.jsについての書籍「TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発」を読了したので、そのレビューを書いていきます。part1は概要部分についてレビューを書いたので、今回はハンズオン部分についてレビューを書いてみます。このNext本が気になっていたのでレビューを知りたい。なんとなくNext.jsを書いていたので、細かな仕組みを知りたい。ハンズオンだけ別のレビューにしたのか?前回までのレビューでは、ハンズオン以外の各技術の説明のセクションについてのレビューを書きました。今回は残りのハンズオン部分のレビューについて書いていきます。「なぜハンズオン部分だけ別のレビューにしたの?」そう思われた人もいると思います。「Next.jsとよく聞くけど、触ってみようかな」という温度感の人がこのハンズオンをやってみると、正直、面食らうと思います(^^;著者は海外ベンチャー経験の実績のある方だけあって、現場に即したコードになっています。TypeScriptの型システム、基本的なJavaScriptの知識、Next.jsの知識、React.jsの知識などなど。技術がモリモリに詰め込まれています。コース料理に例えると、前菜は割烹風の小鉢が並んでいたのに、メインはドカ盛りメニューのような全部盛りのオードブルが来たようなイメージかもしれません。このように書くと、ネガティブな印象が強いかもしれませんが、これが悪いことだとは思っていません。レビューと解説についてハンズオン部分だけのレビューと書きましたが、書籍の大部分をハンズオンが占めているので、全てをレビューするのは困難です。そこで、一部分にフォーカスします。僕がこのハンズオン部分の最も重要な部分は何かと考えて、至った結論は「toPropValueメソッド」です。どのコンポーネントでも利用されているメソッドです。このメソッドを理解すると、あとはすんなり理解できるのではないかと思います。基本機能まず、利用する部分から説明していきます。30px;第一引数には、CSSプロパティを入れ、第二引数には、プロパティの値が入っています。第三引数には書籍で指定された特定のデータが入ります。このメソッドの基本機能としては、CSSの形に直してくれるものです。複雑なのは、次の場合です。64px;}というように、第二引数には特殊なオブジェクトが引数になっており、スクリーンサイズに応じたCSSを作成してくれます。この部分がなかなか理解に苦しむ部分かと思います。メソッド内の説明まず、全体像はこのコードです。theme)};`}結構、ボリューム多いですよね!少しずつ、分解して見ていきましょう!何やら、「if」文がいくつかあるので、そこを目印に分岐しながら考えていきます。第一の分岐はこんな感じですね。undefinedこれは大丈夫だと思います。第二引数のプロパティの値を指定しない場合、undefindeを返却します。次のif文を見てみます。{}これが、第二引数が先ほど機能確認で見たオブジェクトかどうかを判断し、trueの場合、if文の処理に入ります。これは非常にややこしいので、先に、このif文がfalseになり、メソッドの最下部に飛んだ場合を見てみます。theme)};`これが先ほどの機能確認した時の最初のパターンです。theme)このパターンです。新しいメソッドがありますね!toThemeValueIfNeededの中をみていきます。ifで特定のCSSプロパティを探しているものです。theme)を踏まえて、marginだけの例で考えます。value}スッキリしました。SPACE_KEYS.has(propKey)の部分について説明していきます。])このように書かれています。SPACE_KEYSはSetオブジェクトがインスタンス化されたものです。「Setオブジェクトって??何か良いことある?」こう思われた人も多いかと思います。JavaScriptが組み込みで用意してくれているオブジェクトで、キーの検索や特定のキーのCRUD操作ができるような便利なメソッドを利用できるものです。詳しくはMDNを見てみると良いかと思います。それを踏まえて、改めてSPACE_KEYS.has(propKey)を見てみます。この部分は何をしているかというと、propkey(例えば、”margin”など)がSPACE_KEYSの中に存在していれば「true」、無ければ「false」を返却してくれます。If文の条件文の中に入っているということは、SPACEに関する正しいキーが入ったかどうかを確認している、ということです。theme)の部分です。このメソッドが必要か説明します。theme.space[value]にエラーが表示されます。そのエラーの原因は「spaceの中に該当するvalueがあるかは保証されていません」というものです。コンパイラはvalueがSpaceThemeKeysかどうか判断しかねている状況です。行うべきことはコンパイラに対して、「valueはSpaceThemeKeysです」と伝えることです。}この部分はTypeScriptの知識が必要です。「is」がありますね!これはTypeScriptのひとつの機能である、タイプガードというものです。ブランドもののバッグが偽物かどうか判定する方法があるとします。}}このうようなイメージです。このメソッドをくぐったあと、「とあるバッグ」は全て「ブランドバッグ」として認識されます。このように、エディター(コンパイラ)に対象の値の型を伝えたい時に利用するのがタイプガードです。「is」の右側はSpaceThemeKeysとなっているので、最終的には「propはSpaceThemeKeys型」とコンパイラに伝えるものとなっています。theme.space[value]にエラーが表示されなくなります!いやー、なかなか大変ですよね。いう所がTypeScriptが嫌われる原因かもしれません。個人的にはこれをJavaScriptで型無しでエラーを出さずに書き切ることは難しいと感じます。始めは面倒ですが、コード量が増えてくると恩恵が得られると思います!theme.space[value]について補足します。これは「ブラケット記法」と言います。]」でもアクセスすることができます。これも覚えておくと役に立つかもしれません。theme)};の説明が終わりました。ここからようやく、メインメソッドのif文の中身に移っていきます。isResponsivePropType(prop)について詳しく見ます。}メソッドの中身はこのような形をしています。}このような形のオブジェクトかどうかをチェックするものです。baseやsm、mdのいずれかがundefindeではなかったらtrueなので、存在することを保証することになります。}という形が前提で処理されます。続いてif文の中を見ていきます。bar」と表示されます。「in」はinの右側のオブジェクトのキーをforで回していく処理です。}のオブジェクトのキー(baseやsmなど)をforで回している、という意味になります。続きを解説していきます。)};`,for文の中にさらにif文がありますね!この分岐はキーがbaseかそれ以外のsmやmdと区別するためです。最終的に作成したいのはCSSを文字列にしたものです。そこで、baseとsmやmdで区別する必要性が出てきます。theme)};が配列にプッシュされているのがわかります。8px;」のような文字列がプッシュされています。if部分の説明に移ります。}先ほどはresponsiveKeyの「base」を抜き出していましたが、smやmdなどのキーに対しては別の処理が必要になっていきます。CSSのメディアクエリの処理を追加していきます。新しいものが出てきました。BREAKPOINTS[responsiveKey]と言っても、それほど難しいものではありません。}このような形になっており、端的に言えば、smやmdのようなpropKeyとスクリーンサイズの対応付を行なっています。BREAKPOINTS[“md”]の場合、”768px”という値が入っています。BREAKPOINTS.mdと同じです。8px;のような具体的なCSSの文字列が値として格納されています。for文の中のif文の処理の最後は、これです。{${style}}`)ここはCSSの知識が多少ある人だと問題ない部分ではないかと思います。メディアクエリではスクリーンサイズに応じて、当てるCSSプロパティを変更することができます。ここでは、先ほど、BREAKPOINTS[responsiveKey]でキーとスクリーンサイズを対応づけたので、breakpointには具体的なスクリーンサイズが当てはまります。styleにはそのスクリーンサイズの時に当てるCSSプロパティと値が入ります。64px;}の文字列を作成していきます。]のような要素が入ります。お待たせしました!!ようやく最後の処理になります!ふぅ〜。ここまで長かったですね(^^;最後はこの処理です。result.join('\n')これはそれほど難しい処理ではありません。配列のままでは、CSSに適応することができませんので、1つの文字列として結合させる必要があります。その時に利用するメソッドがjoinです。配列の要素を特定の文字列で結合させることができます。バックスラッシュn(‘\n’)は何を表しているかというと、改行を表しています。CSSの記法上、改行して次のプロパティを記述する約束なので、これが必要になります。64px;}のような文字列を作成することができます。非常に長かったですね!これがtoPropValueメソッドの概要です。あー、、いい忘れたことがありました。theme)を見ると、themeが第三引数に存在しています。「毎回、themeを渡す必要があるの??」そう思われたかもしれません。ここは問題ありません!なぜなら、styled-componentsが解決してくれるからです。theme={theme}>これをルートコンポーネントで利用すると、特別、指定しない限り自動的にThemeProviderでpropsで渡したthemeが各toPropValueに適用されます。お疲れ様でした!これで本当に終了です。最後にこの書籍のハンズオン部分はすんなり理解するのは至難の技のような気がします。このtoPropValueを理解できれば、ほとんどの部分を理解できるのではないかと思っています。Next.jsというより、TypeScriptの説明が主になってしまいました(^^;最後に、著者には大変な賛辞を送りたいと思っています。Next.jsはアップデートスピードと多機能性も相まって書籍にするのは大変苦労されたのだと思います。ここに著者の思いの丈を綴ったnoteの記事を貼っておきます。SNSにはネガティブな意見も散見されますが、本当に尊敬の念しかありません。SOA-C02(SysOpsアドミニストレーター)に落ちました。