💻

【Next.js】Prisma ClientはClient Componentではつかえない??

2025/01/05に公開2

Next.js(App Router)で Prisma Client を使用したところ、エラーに遭遇しました。

Component が原因で起こったエラーっぽいですが、よくわからなかったのでまとめました!

バージョン

バージョン
Prisma 5.2.0
Prisma Client 5.2.0
Prisma Studio 0.494.0
Node.js 18.17.0
Next.js 13.4.19

Next.js は、App Router を使用しています

エラー内容

Unhandled Runtime Error
Error: PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `unknown`).
If this is unexpected, please open an issue: https://github.com/prisma/prisma/issues

エラー文を DeepL にかけると、

未処理のランタイム・エラー
エラー エラー: PrismaClientはこのブラウザ環境では実行できません。
予期しないエラーが発生した場合は、https://github.com/prisma/prisma/issues。

原因を考える

エラー文をそのままググってもいいサイトが見つからなかったので、エラー文の意味を考えます。

PrismaClient はこのブラウザ環境では実行できません。

つまり、ブラウザ側(クライアント側)では Prisma Client が使えないってこと??

エラーが出ているコンポーネントを確認してみると、 確かにClient Component になってるな...

"use client";

import prisma from "@/lib/prisma";

export default function AddUser() {
  ...

  const fetchAsyncAddUser = async () => {
    ...

    await prisma.user.create({
      data: {
        name: name,
        email: email,
        posts: {
          create: { title: postTitle },
        },
        profile: {
          create: { bio: profile },
        },
      },
    });
  };

  ...

}

Prisma の HPを確認してみると、SSR や SSG、API Routes で使えるとのこと。

CSR では使えそうにないので、Client Component でも使えなさそうです。

対応方針

やってみる

Route Handlersを Client Component からたたくようにする

今回はこちらの方法でやってみます

修正前

・Client Component

"use client";

import prisma from "@/lib/prisma";

export default function AddUser() {
  ...

  const fetchAsyncAddUser = async () => {
    ...

    // ここからの処理をAPIへ
    await prisma.user.create({
      data: {
        name: name,
        email: email,
        posts: {
          create: { title: postTitle },
        },
        profile: {
          create: { bio: profile },
        },
      },
    });
    // ここまで

    ...

  };

  ...

}

修正後

・Clinet Component

"use client";

import prisma from "@/lib/prisma";

export default function AddUser() {
  ...

  const fetchAsyncAddUser = async () => {
    ...

    // APIのURL
    const url = "http://localhost:3000/api/user";
    // リクエストパラメータ
    const params = {
      method: "POST",
      // JSON形式のデータのヘッダー
      headers: {
        "Content-Type": "application/json",
      },
      // リクエストボディ
      body: JSON.stringify({
        name: name,
        email: email,
        postTitle: postTitle,
        profile: profile,
      }),
    };

    // APIへのリクエスト
    await fetch(url, params);

    ...

  };

  ...

}

・Route Handler
⇒ ./src/app/api/user/route.ts に作成(URL:http://localhost:3000/api/user)

import { NextRequest, NextResponse } from "next/server";

import prisma from "@/lib/prisma";

export async function POST(req: NextRequest) {
  // リクエストボディを展開
  const { name, email, postTitle, profile } = await req.json();

  const res = await prisma.user.create({
    data: {
      name: name,
      email: email,
      // ネストすることで参照先のテーブルに書き込める
      // Postテーブルに書き込む
      posts: {
        create: { title: postTitle },
      },
      // Profileテーブルに書き込む
      profile: {
        create: { bio: profile },
      },
    },
  });

  return NextResponse.json(res);
}

こんな感じで Route Handler を作成してそれをたたくようにしたらうまくいきましたーーー!!!

そもそもデータ更新(追加含め)をClient Componentでやっている時点でおかしかったです。。
ドキュメントを読んで出直してきます

参考文献

https://www.prisma.io/nextjs

https://nextjs.org/docs/app/building-your-application/routing/route-handlers

Discussion

Honey32Honey32

細かい点失礼します。

基本的に

このように、特別な事情がある場合にのみ Route Handlers を使い、そうでない場合には Server Component や Server Actions を 第一の選択肢として 考えるのが良いと思います。

hisuihisui

コメントいただきありがとうございます!!
記事に反映しました!

そもそもClient Componentでデータをいじっていた時点でお門違いでした🙇‍♂️
使用用途によって何を使うかを教えていただき大変助かります!!
Next.jsだけでなく、Reactの方にもドキュメントを探しに行って理解を深めていこうと思います
恥ずかしい内容のエラー対応記事ですが、自分への戒めとしてこのまま公開し続けます

名前にも気を使っていたつもりが。。。
まだまだNext.js勉強中なので他にもあればコメントいただけると助かります🙇‍♂️🙇‍♂️🙇‍♂️