【読書感想文】TypeScript と React/Next.js でつくる実践 Web アプリケーション
最近、書籍を読む機会も多くなってきたので好みのものについては読書感想文を書いていこうと思います。今回は年末年始に注力したかったフロントエンド開発の書籍として 「TypeScript と React/Next.js でつくる実践 Wen アプリケーション」 を読んでみたので、その感想文を書いていきます。
2022 年に発売されたものなのですが、後述する React/Next.js を学ぶ上での書籍として比較サイトに多く出てくるので人気の書籍となっているようです。
執筆時点での自身のフロントエンド開発の経歴としては、本業で 1 年半・副業で半年ほど TypeScript, React/Next.js による経験があります。しかし、実践の中で得た知識が断片的なものだと感じることが多く、そんなところが悩みでした。こちらの書籍を読んでみて TypeScript・React/Next.js の歴史的な背景であったり、それぞれの特徴を網羅的に学べたことが非常に満足のいくポイントでした。また、サンプルアプリケーションを作れる丁寧なガイドもあり、前半で学んだインプットを後半でアウトプットするところまでフォローされていると感じました。
広く浅く書いている部分もあるので、その点は Gemini と問答を繰り返し深掘りするような形で読み進めました。以降では、そんなところも交えつつ感想を書いてみます。
この記事のターゲット
- TypeScript と React/Next.js の基礎を体系的に学びたい方
- Atomic Design を理解しながらサンプルアプリケーションを構築したい方
書籍を読むモチベーション・選んだ経緯
モチベーション
上述した通り、React/Next.js での開発経験は 1 年以上あり調べながらであれば開発できるレベルにはなっていました。しかし、生成 AI の進化により「ただコードが書けて開発ができる」というレベルではエンジニアとしての差別化ポイントになりにくいという危機感を感じており、「根拠を持ってコードを書ける」「他者に周辺知識を交えつつ教えられる」といったもう一段上のレベルを目指したいと考えていました。
そこで基礎を固める意味として学んできた断片的な知識を結んでいくためにも、書籍によるインプットが必要だと感じ年末年始の休暇を使って集中的に本書を読んでみました。(前半の座学パートを調べながらでだいたい 15~17 時間ほどで読み終えました。)
また、Next.js に関しては Page Router での開発経験しかなく App Router についても学びたい思いもありました。
経緯
書籍を選ぶにあたって下記のような比較サイトをいくつか参考にしました。その中でも開発経験はあったことから初級者向けよりは中級者~上級者向けの書籍を読んでみたく、その観点で本書を選びました。
書籍を読むとこんなことに答えられます
下記の質問に答えられる方は、読む必要はないかと思います笑
一方で「え、全然わからない」という方は本書を読んでみるのはありだと思います。
Q1. JavaScript を代替する目的で設計された言語の総称を何と呼ぶか?また、プログラミング言語から別のプラグラミング言語に変換することを何と呼ぶか?
Q2. React の state や props の考え方は単一方向データフロー構造を持つが、これは何というアーキテクチャに影響を受けているか?
Q3. React の特徴として挙げられるものは何か?
Q4. TypeScript のインタフェースと型エイリアスはそれぞれどのように表現されるか?また、これらの機能違いは何か?
Q5. TypeScript の型ガードはどのようなメリットがあるか?
Q6. React Hooks は大別すると何種類あるか?それぞれの特徴は何か?
Q7. Next.js のレンダリング手法は何種類あるか?それぞれの特徴は何か?
Q8. React のコンポーネント指向の設計と相性が良いとされているデザインシステムは何か?
Q9. 上記のデザインシステムはどのような階層でどういった役割を持つか?
書籍の構成と中身を少々
本書は 1~7 章で構成されていて、前半の 1~4 章は「基礎知識を学べる座学パート」と後半の 5~7 章は「実際にサンプルアプリケーションを構築する実践パート」となっています。
読書感想文ということなので、各章の概要というよりは特に印象的だった部分に触れていきます。
1章 Next.js と TypeScript によるモダン開発
フロントエンド開発の歴史をサマってくれていて、どのような変遷で現在のモダンなフロントエンド開発に至ったかを知ることができました。その中でも知らない概念だったり、単語レベルでは知っているけど、、といったものが多かったので、個人的にはここだけでも学べて価値があったと思っています。
Q1~Q3 は 1 章の中で学べます。
Q1. JavaScript を代替する目的で設計された言語の総称を何と呼ぶか?また、プログラミング言語から別のプラグラミング言語に変換することを何と呼ぶか?
JavaScript を代替する目的で設計された言語を総じて、AltJS と呼びます。由来は「代替 JavaScript 言語」ってことで「Alternative JavaScript」を略して、このように呼ぶみたいです。
プログラミング言語から別のプログラミング言語に変換することを トランスパイル と呼びます。今回でいえば、TypeScript から JavaScript に変換する処理に当たります。
Q2. React の state や props の考え方は単一方向データフロー構造を持つが、これは何というアーキテクチャに影響を受けているか?
React ではデータは親コンポーネントから子コンポーネントへ一方向に流れていきます。これを単一方向データフロー構造と呼んでいます。これは、子コンポーネントでは親コンポーネントから渡されたデータを直接変更できないこととして、データの流れを明確にするメリットがあります。
これは Flux アーキテクチャに影響を受けているようです。React と Flux はどちらも Meta(当時 Facebook) によって開発されており、React の開発時に Flux アーキテクチャの概念を設計に取り入れたようです。
Q3. React の特徴として挙げられるものは何か?
本書では、下記の 5 点が挙げられていました。
- 仮想 DOM
- 宣言的 UI
- 単一方向のデータの受け渡し
- コンポーネント指向・関数コンポーネント
- Flux アーキテクチャとの親和性
「仮想 DOM」「宣言的 UI」の 2 点に触れます。
仮想 DOM は、実際の DOM を直接操作する代わりにメモリ上に軽量な JavaScript である仮想 DOM を作成して、変更が起こった場合の差分を特定するのに利用されます。特定された差分のみが更新されることで DOM の更新回数を最小限に抑えることができます。
宣言的 UI は、UI の状態を「どのように」表示するかではなく、「何を」表示するかを宣言的に記載することができます。何を表示するかがコードから明確に読み取れるため、コードの可読性が向上します。
命令的 UI サンプルコード
const items = ["Item 1", "Item 2", "Item 3"];
const listContainer = document.getElementById("list-container");
// リストを動的に生成する
function renderList() {
listContainer.innerHTML = ""; // 既存のリストをクリア
for (let item of items) {
const listItem = document.createElement("li");
listItem.textContent = item;
listContainer.appendChild(listItem);
}
}
// 初期レンダリング
renderList();
// データが更新された場合の再レンダリング(例)
function updateList() {
items.push("Item 4");
renderList();
}
const updateButton = document.getElementById('update-button');
updateButton.addEventListener('click', updateList);
<div id="list-container"></div>
<button id="update-button">Update List</button>
宣言的 UI サンプルコード
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
function MyList() {
const [items, setItems] = useState(["Item 1", "Item 2", "Item 3"]);
const updateList = () => {
setItems([...items, "Item 4"]);
};
return (
<div>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={updateList}>Update List</button>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<MyList />);
<div id="root"></div>
2章 TypeScript の基礎
データ型の話がこの章の中心でした。普段使っているデータ型はもちろんですが、ユニオン型と相対するインターセクション型や Never 型といった馴染みのないデータ型も学ぶことができました。
実践の中で自然に学んだものが大半ですが、知識として知っておくことで実装の幅が広がると感じました。例えば、Enum 型もなんとなくで文字列ベースを利用していましたが、数値ベースも存在していること・何もしないと 0 から自動でインクリメントされて設定されることなど、ケースによって使い分けることができそうだなーとか新たな発見も多かったです。
Q4~Q5 は 2 章の中で学べます。
Q4. TypeScript のインタフェースと型エイリアスはそれぞれどのように表現されるか?また、これらの機能違いは何か?
インタフェース型は interface Hoge {}
、型エイリアスは type Huga = {}
のように表現できます。インタフェース型は型エイリアスと似ていますが、より拡張性がの高い機能のようです。
例えば、下記のように一度インタフェース型を定義した x, y に対する interface Point
に新たに z を追加で定義することができます。TypeScript ではかっちりデータ型を定義して変更できないイメージだったので、このような拡張性の高い機能があることには驚きました。一方で、これが乱発すると最終的なデータ型を追いづらくもなりそうだなと思いました。
interface Point {
x: number;
y: number;
}
function printPoint(point: Point) {
console.log(`x座標は${point.x}です`)
console.log(`y座標は${point.y}です`)
console.log(`z座標は${point.z}です`)
}
interface Point {
z: number;
}
// 引数のオブジェクトにzが存在しないためコンパイル時にエラーになります
printPoint({ x: 100, y: 100 })
// 問題なく動作します
printPoint({ x: 100, y: 100, z: 200 })
Q5. TypeScript の型ガードはどのようなメリットがあるか?
型ガードとは、if 文や switch 文の条件分岐にて型のチェックを行った際に、その条件分岐ブロック以降は変数の型を絞り込まれる遂論を行なってくれます。
これも実践の中で、変数を扱う際に型の選択肢を絞り込むために当たり前にやっていましたが、型ガードという概念であることを知りました。メリットとしては、型ガードによって該当ブロックは型を絞り込めるためより安全に実装することができます。また、コンパイラからの警告も回避することができます。
function addOne(value: number | string) {
if (typeof value === 'string') {
return Number(value) + 1
}
return value + 1
}
console.log(addOne(10)) // 11
console.log(addOne('20')) // 21
3章 React/Next.js の基礎
React Hooks を網羅的に学べたのが印象的な章でした。こちらも前章の TypeScript のデータ型同様に普段利用しているフックに加えて、馴染みのないフックも学べたのが有意義でした。また、普段利用しているフックについても知識が足りていない部分を発見できて、さらに調べるきっかけとなったのですぐに実践活かせるインプットができました。
逆にいうと、各フックにそこまで深くは触れていないので、もっと知りたいと思った場合には別で調べる必要があります。
例えば、useEffect
の説明として「props や state が更新され、再描画が終わった後に処理が実行されます。依存配列を指定することで、特定のデータが変化した時だけ処理を行うように設定できます。」とだけあります。(理解する必要があるかどうかさておき)これをより理解するには、更新や再描画が公式の説明にある「Trigger a render」「Rendering the component」「Committing to the DOM」といった React の画面表示プロセスのどこにあたるのか理解する必要があったりします。
Q6~Q7 は 3 章の中で学べます。
Q6. React Hooks は大別すると何種類あるか?それぞれの特徴は何か?
大別すると下記の 7 種類が本書では紹介されています。
- 状態のフック
- Context のためのフック
- ref のフック
- 副作用のフック
- メモ化のフック
- カスタムフックや開発時の利用するフック
この中でも Context のためのフックの useContext
を初めて知りました。普段はローカルステート管理として useState
やグローバルステート管理として Redux
を利用しています。その中間にあたるような挙動が可能な Context を使っていなかったので、Context の概念を知ったことで実装の幅が広がった気がしました。
Q7. Next.js のレンダリング手法は何種類あるか?それぞれの特徴は何か?
下記の 4 種類が本書では紹介されています。
- クライアントサイドレンダリング(CSR)
- サーバーサイドレンダリング(SSR)
- 静的サイト生成(SSG)
- インクリメンタル静的再生成(ISR)
実はここらへんは理解できているようで全く理解できていませんでした。しかし、このパートで図を交えながら説明よむことで多少なりとも理解を深めることができ、満足度が高かったです。特に インクリメンタル静的再生成(ISR) の挙動が、事前にレンダリングしたページに対して有効期限を設定でき、その期限が切れてアクセスされるとバックグラウドで再生成されてまたキャッシュされるという仕組みであることを理解できました。
4章 コンポーネント開発
コンポーネント設計に Atomic Design の考え方を適用する話が記述されています。
Q8~Q9 は 4 章の中で学べます。
Q8. React のコンポーネント指向の設計と相性が良いとされているデザインシステムは何か?
こちらはもう上記に書いてしまいましたが、Atomic Design です。Atomic Design の特徴としては、デザインを階層的に定義することで、一貫性を保ち、管理しやすくなると記述されています。
こちらは単語レベルでは知っていたもののちゃんと調べる機会がなかったので、非常に学びが深かったです。この考えを知っておくと、コンポーネントをどの粒度で設計すればいいのかを考える時に役立ちそうです。また、実際のコードの中でも下記で説明するような Atomic Design の粒度でディレクトリを切っていることもあるので、コードを理解する上でも役立ちました。
Q9. 上記のデザインシステムはどのような階層でどういった役割を持つか?
Atomic Design は下記の 5 つの階層に分かれます。上が最小粒度で下にいくごとに粒度が大きくなります。
- Atoms:最小の要素で、これ以上分割できない
- Molecules:複数の Atoms を組み合わせて構築
- Organisms:Molecules よりもより具体的な要素
- Templates:ページ全体のレイアウト
- Pages:ページそのもの
ただ、Atomic Design はデザインの方法論であるため、それぞれの階層でプログラム的にどのように役割・振る舞いを持つかは開発チームで認識を合わせる必要があるようです。
5~7章 アプリケーション開発
5 章以降はサンプルアプリケーションの開発パートになります。
- 5章:環境セットアップなど
- 6章:Atomic Design によるコンポーネント作成・ページ作成など
- 7章:デプロイやロギングなど
せっかくなので、インプットしたことをアウトプットするがてらサンプルアプリケーションを作成しようと思ったのですが、個人的に惜しい部分がありました。
惜しい部分を書く前に感想を書いておくと、1 つ 1 つのコンポーネントを 0 ベースで設計する経験が詰める章となっていました。また、簡易的なバックエンドをすぐに利用できるリポジトリも用意されているので storybook 上だけでなく、フロントエンドに集中したサンプルアプリケーションの開発できる点も良かったです。
惜しかったところ
また、Next.js に関しては Page Router での開発経験しかなく App Router についても学びたい思いもありました。
モチベーションのところでこんなことを書いていました。そして、5 章以降のサンプルアプリケーション開発は Page Router で実装されていました。
本書が発売されたのが 2022 年 7 月で、App Router のリリースは 2022 年 10 月だったので当然なのですが。そこまで考えずに購入していました。。
Page Router は普段から利用しているのでイメージはついていますし、Atomic Design でのコンポーネント設計は学びがあるものの普段は Mantine を利用しているので 0 ベースでやる必要もないかなと個人的に感じました。
ただ、ここで終わってしまうのはもったいないと思い、App Router でこのサンプルアプリケーションを実装すればいいのでは!となりました。
ということで、次の記事では「App Router でサンプルアプリケーションの実装」という感じで執筆したいと思います。(絶賛実装中です。)
さいごに
今まで書籍を読んだ時は Zenn の本かスクラップに個人用としてメモを取る程度でしたが、初めて書籍の内容を紹介 & 感想を述べる記事を書いてみました。初めてのパターンなので、公開するのに少し緊張します。
2 年前の本ではあるので「もう知っているわ」という方も多いと思いますが、これからフロントエンドに入門する方やもしくは私のように入門はできているけどレベルアップをしたい方の書籍選びの参考になれば幸いです。
Discussion
I don't know Japanese, but I'm interested in this book, and I'm currently working in the front-end React/Next.js sphere. Tomonori Hayashi / @pHaya72, could you publish this book in English?