🐶

Next.js 13 のSSRでコンポーネントからデータフェッチしてみる

2022/10/31に公開

Next.js 13 でコンポーネント単位でのデータフェッチが簡単になった

Next.js 13 から、コンポーネント内でReactのuse関数によるデータフェッチができるようになりました。
SSRにおいてページコンポーネントでgetServerSidePropsを使ってコンポーネントに値を渡すという処理を書かなくても良くなりました。

Next.js 13 でプロジェクトを作成

Next.js 13 のベータ版ドキュメントを参考に、プロジェクトを作成します。
Getting Started | Next.js

yarn create next-app --experimental-app

作成されるプロジェクトのディレクトリ構成は以下の通り。
Next.js 13では新しくapp/ディレクトリを自動ルーティングとして使用できます。

.
├── app
│   ├── globals.css
│   ├── layout.tsx
│   ├── page.module.css
│   └── page.tsx
├── node_modules
├── pages
│   └── api
│       └── hello.ts
├── public
│   ├── favicon.ico
│   └── vercel.svg
├── .eslintrc.json
├── .gitignore
├── next-env.d.ts
├── next.config.js
├── package.json
├── README.md
├── tsconfig.json
└── yarn.lock

データをフェッチするコンポーネントを用意する

サーバーサイドの確認用環境変数を設定。

.env.development.local
IS_SSR=TRUE

https://dog.ceo/から犬の画像URLを取得するコンポーネントを作成してみます。
SSRされることの確認用に、環境変数へのアクセスとレンダリング分岐を実装しています。

app/components/DogImages.tsx
import { use } from 'react'

type Dogs = {
  message: string[],
  status: string
}

async function getDogs(): Promise<Dogs> {
  const res = await fetch('https://dog.ceo/api/breed/labrador/images/random/6')
  return await res.json()
}

export default function DogImages() {
  const dogs = use(getDogs())
  console.log(`{RENDERED: DogImages{SSR: ${process.env.IS_SSR}}}`)

  return (
    <pre>
      {typeof window === 'undefined'
        ? JSON.stringify(dogs, null, 2)
        : null
      }
    </pre>
  )
}

app/でトップページとなるpage.tsxDogImagesコンポーネントを組み込みます。

app/page.tsx
import Image from 'next/image'
import styles from './page.module.css'
import DogImages from './components/DogImages'

export default function Home() {

  return (
    <div className={styles.container}>
      <main className={styles.main}>
        <DogImages /> // 追加
        <h1 className={styles.title}>
          Welcome to <a href="https://nextjs.org">Next.js 13!</a>
        </h1>
// 以下省略

ブラウザで確認する

開発用サーバーを起動します。

yarn dev

http://localhost:3000にアクセスすると、取得した情報が表示されます。
画面を更新すると再フェッチされ、ターミナルの出力に{RENDERED: DogImages{SSR: TRUE}}と表示されコンポーネントでSSRが働いていることも確認できます。

今後の展望

ReduxのisLoadingなどの実現を試してみたくなりました。
ページコンポーネント以外でデータフェッチングできるようになったのは良い変更だと思います。
Container/PresentatinalパターンがNext.jsできれいに書けるようになりそうですね。

Discussion