【Next.js v13.4 AppRouter】触ってみた備忘録（public repository付き）

## 目次
[1.はじめに](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#1%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
[2.この記事の対象者](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#2%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E5%AF%BE%E8%B1%A1%E8%80%85)
[3.今回作ったアプリの要件](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#3%E4%BB%8A%E5%9B%9E%E4%BD%9C%E3%81%A3%E3%81%9F%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A6%81%E4%BB%B6)
[4.成果物](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#4%E6%88%90%E6%9E%9C%E7%89%A9)
[5.とりあえず公式DOCや他記事を読んだまとめメモ](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#5%E3%81%A8%E3%82%8A%E3%81%82%E3%81%88%E3%81%9A%E5%85%AC%E5%BC%8Fdoc%E3%82%84%E4%BB%96%E8%A8%98%E4%BA%8B%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A0%E3%81%BE%E3%81%A8%E3%82%81%E3%83%A1%E3%83%A2)
[6.開発時のポイント](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#6%E9%96%8B%E7%99%BA%E6%99%82%E3%81%AE%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88)
[7.まとめ](https://qiita.com/kimukimu01/items/b471afb7ef6f17ab0113#7%E3%81%BE%E3%81%A8%E3%82%81)

# 1.はじめに
2023年5月5日に公開されたNext.js v13.4でAppRouterが安定版リリースとなりました。
インパクトのある大きなリリースだったので、著者も遅ればせながらAppRouterをもちいて簡単なアプリを作成してみました。
その過程で学んだことを備忘録としてこちらに残しています。

※outputも兼ねて実装/記述してるため、間違いあればご指摘お願いします。

# 2.この記事の対象者
* `React.js`と`Next.js`の基本実装に慣れている方
* 実際のコードを見て触れて学びたい人

# 3.今回作ったアプリの要件
* トップページ
  * 本日のアート情報を5件表示（海が好きなので海に関する作品を指定しています🏄）
  * 作品タイトル押下で作品情報に遷移
* 作品情報ページ
  * 作品の詳細情報を表示
  * お気に入りボタン押下で疑似お気に入り登録（表示上のみの疑似機能）
  * トップに戻るボタン押下でトップページに遷移

# 4.成果物
以下のリポジトリに成果物置いてます。
https://github.com/YuriKimura01/study-app-router

# 5.とりあえず公式DOCや他記事を読んだまとめメモ
* 全てのReactコンポーネントをサーバー側でレンダリングすることにしたよ
* app配下で便利関数置くファイル作れるようになったよ（例：app/_utils/xxx.js）
  * 上記ファイルはルーティングから除外される
* App Routerの`fetch`は気をつけて
  * 初回コール時にレスポンスを自動でキャッシュする
  * 2回目以降は1回目のresをそのまま返す
* app/layout.jsでpage.jsの外側の部分（`<html>` や `<body>`）を定義できるようになったよ
* Server Componentsとして基本的には全てサーバーでレンダリングされるよ
  * 通信や条件分岐や反復処理を終えた、最終的なビューツリーのデータだけがブラウザに送られる
  * コンポーネントを返す関数自体を非同期関数として扱うことが可能
  * クライアントでコンポーネントをレンダリングする場合はファイル先頭に`"use client"`を書く
  * SSRとは違う機能。SSRは初期ロード時に有効

# 6.開発時のポイント
### layout.js

`metadata`か`generateMetadata`を利用してexportするだけでmetadataの設定完了。
`Metadata`というtypeも用意してくれていました。

```react:layout.tsx
export const metadata: Metadata = {
  title: "Today's your art",
  description: `check your favorite art!`,
};
```

`<html>`や`<body>`等の外側の部分もここで記述。

```react:layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>
        <header>
          <h1>Today's your art</h1>
        </header>
        {children}
      </body>
    </html>
  );
}
```

### style

著者が好きな`styled-components`はServerComponentsでは利用できない為、原点回帰で`CSS Modules`を選択。
ReactチームとServerComponentsでも利用出来るように取り組んでいるみたいです。そう遠くない未来で利用できる時が来そうですね。
参考：https://nextjs.org/docs/app/building-your-application/styling

### イベントハンドラ
onClickを利用するコンポーネントは"use Client"を利用して、クライアントコンポーネントにする必要がある。

### Linkコンポーネント
next/linkで提供されている`<Link>`でのherf指定はダイレクトパス指定のみしか許容していない。
参考：https://nextjs.org/docs/messages/app-dir-dynamic-href

```react:ArtInfo/index.tsx
<Link href={`/info/${id}`} className={styles.title}>
  {title}
</Link>
```

### app配下でのpage設定
下記キャプチャのようにURL名のディレクトリ配下のファイルはpage.tsxとしないとpageとして認識してもらえません。
![スクリーンショット 2023-07-27 15.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626928/75f1630d-63d3-0601-ed7c-ed9ea73dd393.png)

### paramの取得方法
**ServerSide Components**：propsで取得できる
```react:info/[id]/page.tsx
export default async function InfoPage({ params }: Props) {
  const artInfoData = await fetchArtDetailInfo(params.id);
```
layout.tsx：https://nextjs.org/docs/app/api-reference/file-conventions/layout#params-optional
page.tsx：https://nextjs.org/docs/app/api-reference/file-conventions/page#params-optional

**Client Components**：useParams()を利用して取得
https://nextjs.org/docs/app/api-reference/functions/use-params


# 7.まとめ
今回は備忘録としてカジュアルに一つの記事とさせていただきました。
[6.開発時のポイント]は同じように躓く方も少なく無いかと思います。少しでも皆様のお力になれると幸いです。

何かお気づきの点等あればお気軽にコメントください。
最後までお読みいただきありがとうございました！またどこかでお会いしましょう！！