React + TypeScript: Next入門01 チュートリアルの作例を一からつくってみる

[Next.js](https://nextjs.org/)の公式サイトには[チュートリアル](https://nextjs.org/learn/basics/create-nextjs-app)解説があります。その作例[`https://next-learn-starter.vercel.app`](https://next-learn-starter.vercel.app/)をTypeScriptも加え、一からつくってみようというのがこのチュートリアルシリーズの目的です。

Next.js公式チュートリアルは、なかばでき上がったプロジェクトのコピーにコードを書き加えるかたちで進められます。手っ取り早いものの、Next.jsを使った開発の流れがよくわかりません。また、[TypeScript](https://nextjs.org/learn/excel/typescript)については、完成したJavaScriptの作例にあとから型づけを与える説明です([`next-learn/basics/typescript-final/`](https://github.com/vercel/next-learn/tree/main/basics/typescript-final))。

本チュートリアルシリーズは、プロジェクトにはじめからTypeScriptを加えます。そのうえで、一から公式作例と同じアプリケーションをつくってみましょう。


# React + TypeScript + Nextのひな形プロジェクトをつくる
[Create Next App](https://nextjs.org/docs/pages/api-reference/create-next-app)で[TypeScriptプロジェクト](https://nextjs.org/docs/pages/building-your-application/configuring/typescript#create-next-app-support)をつくるのがつぎのコマンドです。`--ts`フラグがTypeScriptを指します。

```terminal
npx create-next-app@latest --ts
```

プロジェクト名(ここでは`react-typescript-next-example`)を含め、つづいて示される質問に答えてください。つぎの例では、ESLintも加えました。

> ✔ What is your project named? … **react-typescript-next-example**
✔ Would you like to use ESLint with this project? … No / <ins>**Yes**</ins>
✔ Would you like to use `src/` directory with this project? … <ins>**No**</ins> / Yes
✔ Would you like to use experimental `app/` directory with this project? … <ins>**No**</ins> / Yes

プロジェクトのディレクトリに切り替えたあと、`npm run dev`コマンドを入力すればひな形プロジェクトのページがローカルサーバー`http://localhost:3000`で開きます(図001)。

#### 図001■ローカルサーバーで開いたひな形プロジェクト
![qiita_2301001_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/baad853a-e9d7-9252-6963-f297882faff0.png)


# トップページを書き替える
まずは、アプリケーションのトップページを書き替えましょう。モジュールは`pages/index.tsx`です。関数コンポーネント`Home`は、つぎのように改めてください。

```react:pages/index.tsx
export default function Home() {
	return (
		<>
			<section>
				<h1>
				Learn <a href="https://nextjs.org/learn/foundations/about-nextjs?utm_source=next-site&utm_medium=nav-cta&utm_campaign=next-website">Next.js!</a>
				</h1>
				<p>Get started by editing <code>pages/index.js</code></p>
			</section>
		</>
	);
}
```

そして、アプリケーション全体に適用されるグローバルなCSSが`styles/globals.css`です。ひな形プロジェクトのCSSの定めは使いません。公開されている作例のGitHubコード[`next-learn/basics/typescript-final/styles/global.css`](https://github.com/vercel/next-learn/blob/main/basics/typescript-final/styles/global.css)で上書きしてください。トップページはつぎの図002のように改められたはずです。

#### 図002■書き替えられたトップページ
![qiita_2301001_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/8816ee37-d505-133c-5b42-8c57e80b1634.png)


# ページを加える
さらに、ページを加えましょう。Next.jsでは、ページは[`pages`ディレクトリ](https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts)に、Reactコンポーネントで加えます。ディレクトリ`pages`に加えた`posts`に、つぎのモジュール`pages/posts/first-post.tsx`を定めてください。

```react:pages/posts/first-post.tsx
import type { FC } from 'react';

const FirstPost: FC = () => {
	return <h1>First Post</h1>;
};
export default FirstPost;
```

ページのルートは、Reactコンポーネントモジュールの名前によって決まります。たとえば、つぎのとおりです。

* `pages/index.tsx`のルート: `/`
* `pages/posts/first-post.tsx`のルート: `/posts/first-post`

コンポーネントの名前は、自由に定められます。ただし、必ず`default`で`export`しなければなりません(「[Create a New Page](https://nextjs.org/learn/basics/navigate-between-pages/pages-in-nextjs#:~:text=The%20component%20can%20have%20any%20name%2C%20but%20you%20must%20export%20it%20as%20a%20default%20export.)」)。`http://localhost:3000/posts/first-post`を開けば、新たに加えたページが表示されるでしょう(図003)。

#### 図003■新たに加えたページ
![qiita_2301001_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/55f6adb1-1e81-0008-b3e2-c5656f629f8a.png)


# `Link`コンポーネントを使う
Next.jsでアプリケーション内のページ遷移を制御するのが`Link`コンポーネントです(「[\<Link\>](https://nextjs.org/docs/pages/api-reference/components/link)」参照)。コンポーネントを`import`したら、`<a>`要素と同じく、リンク先は`href`プロパティに定めてください(他のプロパティについては「[Props](https://nextjs.org/docs/pages/api-reference/components/link#props)」参照)。モジュール`pages/index.tsx`の`<h1>`要素はつぎのように書き替えます(図004)。

```react:pages/index.tsx
import Link from 'next/link';

export default function Home() {
	return (
		<>
			<section>
				<h1>
					{/* Learn <a href="https://nextjs.org/learn/foundations/about-nextjs?utm_source=next-site&utm_medium=nav-cta&utm_campaign=next-website">Next.js!</a> */}
					Read <Link href="/posts/first-post">this page!</Link>
				</h1>
				{/* <p>Get started by editing <code>pages/index.js</code></p> */}
			</section>
		</>
	);
}
```

#### 図004■トップページのリンクを`Link`コンポーネントで書き替えた
![qiita_2301001_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/b66a2a65-b1e9-eb11-94ed-f56696c42982.png)

なお、Next.js 12.2になるまでは、`Link`コンポーネントは`<a>`要素を包む必要がありました。けれど、もはや`<a>`要素は要りません(「[React + Next.js: Linkコンポーネントで\<a\>要素を包んだらサーバーエラーになった](https://qiita.com/FumioNonaka/items/0e97dca13528fb3366a0)」参照)。

遷移先の`pages/posts/first-post.tsx`からトップページに戻るためのリンクも、つぎのように`Link`コンポーネントで加えましょう(図005)。

```react:pages/posts/first-post.tsx
import Link from 'next/link';

const FirstPost: FC = () => {
	// return <h1>First Post</h1>;
	return (
		<>
			<h1>First Post</h1>
			<h2>
				<Link href="/">← Back to home</Link>
			</h2>
		</>
	);
};
```

#### 図005■遷移先ページにトップへ戻るリンクを追加
![qiita_2301001_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/b39c3a48-64a4-bbed-8851-b90cbf1f0441.png)


# クライアントサイドナビゲーション
同じNext.jsアプリケーション内でページ遷移するとき働くのが「クライアントサイドナビゲーション」([Client-Side Navigation](https://nextjs.org/learn/basics/navigate-between-pages/client-side#:~:text=5-,Client%2DSide%20Navigation,-The%20Link%20component))です。ページが変わるとき、クライアント側のJavaScriptが用いられます。そのため、ブラウザからサーバーにリクエストを送るデフォルトの切り替えより、処理が速められるのです(「[nextjs with typescript:04 クライアントサイドナビゲーション、Linkタグ](https://note.com/fz5050/n/n0343ee506321)」参照)。

試しに、トップページで[デベロッパーツール]を使って、`<body>`要素の背景色(`background`)を黄色(`yellow`)に変えてみましょう(図006)。そのうえで、ページを遷移してください。切り替えたページでも、背景は黄色のままのはずです。クライアントサイドナビゲーションにより、ブラウザはページ全体のリロードはしません。

#### 図006■[デベロッパーツール]でトップページの`<body>`要素の背景色を変える
![qiita_2301001_006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/c0543458-0e5b-36b6-9531-a3246539dd8c.png)

なお、`Link`コンポーネントでなく`<a>`要素でリンクした場合、ページ遷移はデフォルトに戻り、ブラウザがページ全体を更新することにお気をつけください。

また、Next.jsはコードを自動的に分割します。それぞれのページごとに、必要なコードしかロードはされません。たくさんのページで構成されたサイトであっても、各ページは素早く読み込まれます。ロードされるのはそのページに必要なコードだけですから、エラーを生じたページがあっても他に影響は与えないのです。

さらに、プロダクションビルドでは、Next.jsは`Link`コンポーネントがピューポートに入ると、自動的にリンク先ページのコードをバックグラウンドで先読みします。リンクをクリックしたときには、そのページに直ちに移れるでしょう。

ここまでのコードを掲げたのがつぎのソース01です。

#### ソース01■Next入門01 チュートリアルの作例を一からつくってみる
https://github.com/FumioNonaka/react-typescript-next-example/tree/react-typescript-next-example-01

本稿では、Next.jsの基本的な操作について解説しました。次回からは、Next.js公式作例にコードを近づけてゆきます。


## React + TypeScript: Next入門シリーズ

* Next入門01 チュートリアルの作例を一からつくってみる
* [Next入門02 イメージとメタデータおよびCSSを扱う](https://qiita.com/FumioNonaka/items/4df0bfe8538eb346cad5)
* [Next入門03 プリレンダリングとデータ取得](https://qiita.com/FumioNonaka/items/82fd364d746de5206749)
* [Next入門04 動的ルートを定める](https://qiita.com/FumioNonaka/items/dd9b21834d3634e36540)