はじめに
サーバーサイドとクライアントサイドの挙動についてつまづいたところがあったのでまとめておきます
問題
以下のコードを実行したところエラーが出ました
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としてシリアライズすることができません
おわりに
この挙動を知らなかったのでしれてよかったで