0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supportedエラーが出る

Posted at

はじめに

サーバーサイドとクライアントサイドの挙動についてつまづいたところがあったのでまとめておきます

問題

以下のコードを実行したところエラーが出ました

export default async function Popular() {
type ArticleJson = {
  title: string;
  description: string;
  author: string;
  cretedAt: number;
  viewCount: number;
};

const getArticles = async () => {
  const response = await fetch("http://localhost:3000/api/blogs/popular");
  const data = await response.json();
  return data;
};

export default async function Popular() {
  const articlesData = (await getArticles()) as ArticleJson[];
  const articles = articlesData.map((article: ArticleJson) => {
    return new Article(
      article.title,
      article.description,
      article.author,
      article.cretedAt,
      article.viewCount
    );
  });

  if (!articles) return <div>Loading...</div>;

  return (
    <div className="container mx-auto px-4 py-8">
      {/* ... 残りのコード ... */}
      <PopularArticleList articles={articles} />
    </div>
  );
}
Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.   <... article={{title: ..., description: ..., author: ..., createdAt: ..., viewCount: ...}}>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

ここでPopularArticleListはクライアントサイド(use client)になっています

解決方法

export default async function Popular() {
  const articlesData = (await getArticles()) as ArticleJson[];
  // クラスのインスタンスを作成せず、プレーンオブジェクトとして渡す
  const articles = articlesData.map((article: ArticleJson) => ({
    title: article.title,
    description: article.description,
    author: article.author,
    createdAt: article.cretedAt,
    viewCount: article.viewCount
  }));

  if (!articles) return <div>Loading...</div>;

  return (
    <div className="container mx-auto px-4 py-8">
      {/* ... 残りのコード ... */}
      <PopularArticleList articles={articles} />
    </div>
  );
}
type ArticleProps = {
  title: string;
  description: string;
  author: string;
  createdAt: number;
  viewCount: number;
};

export function PopularArticleList({ articles }: { articles: ArticleProps[] }) {
  // ... コンポーネントの実装 ...
}

クラスではなくオブジェクトを渡すことでうまくいきました

このエラーの原因は、React Server Components (RSC) とClient Componentsの間のデータの受け渡し方に関する制限に起因します

Server ComponentsからClient Componentsにデータを渡す際、そのデータは必ずネットワーク越しに送信される必要があります
そのため、データは必ずJSONとしてシリアライズ可能である必要があります
クラスのインスタンスはメソッドや特別なプロトタイプを持っているため、単純にJSONとしてシリアライズすることができません

おわりに

この挙動を知らなかったのでしれてよかったで

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?