🍆

【Next.js + Supabase】SSR(Server Components)でデータ取得と出力するには?【App Router】

2023/10/25に公開

Next.js 13から導入された「Server Components」という概念によって、Supabaseの利用環境も大きく変わったことと思います。

Server Componentsでデータ取得してSSRするにはどうすればいいか分からないという方もいると思うので記事化することにしました。

※不要な要素を削ぎ落とした最低限な書き方にしています。実際に使うときは自分なりに使いやすい方法を考えてみましょう!

【はじめに】@supabase/ssr を使用しよう!

色々と面倒なことは Supabase 公式パッケージの「@supabase/ssr」がオススメです。

npm install '@supabase/ssr

でインストールしておきましょう!

それでは、下記から書き方を説明します!

Server Components を作ってみよう

データ取得と出力を行うコンポーネントを作成します。

posts.tsx
import { cookies } from "next/headers";
import { createServerClient } from "'@supabase/ssr";

export const PostsView = async () => {
  const cookieStore = cookies();
  
  const supabase =
    createServerClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
      {
        cookies: {
          get(name: string) {
          return cookieStore.get(name)?.value;
        },
      }
    });
  const { data:posts } = await supabase.from('posts') .select(`*`);
  
  return (
    <>
      {posts.map((thePost) => (
        <div key={thePost.uuid}>
	  <p className="title">{thePost.title}</p>
	  <p className="text">{thePost.contents}</p>
	</div>
      ))}
    </>
  );
}

Supabaseの posts テーブルからデータを取得し、
結果を元に各要素を出力してくれるコンポーネントです。

次に、このコンポーネント自体を出力するための記述をする必要があります。

Suspense でデータ取得状況に応じて表示を切り替えよう

先程作った PostsView コンポーネントはデータ取得を伴うため、必ずしもすぐに表示されるとは限りません。データ取得が完了しない間は「読み込み中」などのテキストを表示させたいと思います。

page.tsx
import { Suspense } from "react";
import { PostsView } from "@/components/posts";

export default function HomePage () {
  return (
    <>
      <Suspense fallback={<p>データ読み込み中...</p>}>
        <PostsView />
      </Suspense>
    </>
  )
}

これで先程の PostsView を出力できます。
ポイントは Suspenseです。 Suspense はReactが提供する機能で、処理が終わるまで fallback に指定したコンポーネントを出力してくれて、処理完了後は <PostsView /> を出力してくれます。

データ取得に応じて useState 等で状態管理を行う必要が無い便利な機能です!

Suspenseで囲ったコンポーネントはSSRされるのでSEO的にも優れています。
また、next/link でページ遷移した時にデータ取得がすぐに完了しないときは fallback のコンポーネントを出力してくれるのでユーザーに状況が伝わりやすくてUX的にも優れています。

データ取得に失敗したときの表示はどうすればいいの?

データ取得は100%成功するとは限りません。エラー時にはどうすればいいのかも掲載しておきます。

ErrorBoundary という仕組みが用意されていますが、現状は https://www.npmjs.com/package/react-error-boundary のようなパッケージを使って実装しておくと良いかと思います。

Discussion