
錯誤範例
下面這段程式碼是直接用 fetch 呼叫 /api/posts API:
// src/app/[lng]/(home)/_components/PostsSection.tsx
import Grid from "@mui/material/Grid";
import PostCards from "@/components/UI/PostCards";
export default async function PostsSection() {
// SSR 取得文章資料
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
const posts = await fetch(`${baseUrl}/api/posts`).then((res) => {
if (!res.ok) {
throw new Error("Failed to fetch posts");
}
return res.json();
});
return (
<Grid container spacing={2} columns={12}>
<PostCards posts={posts.data} />
</Grid>
);
}
📌 看似正常,但實際跑起來會遇到 fetch error,原因就是 RSC 並不適合用這種方式去打 API。
正確範例
解法是直接使用 Sanity 提供的 client.fetch,在 Server Component 中撈資料,不透過 /api/posts。
// src/app/[lng]/(home)/_components/PostsSection.tsx ← Server Component(不要 "use client")
import Grid from "@mui/material/Grid";
import PostCards from "@/components/UI/PostCards";
import {client} from "@/sanity/lib/client"
import { PostDoc } from "@/schema/type/post";
export default async function PostsSection() {
const posts = await client.fetch<PostDoc[]>(
`*[_type == "post"] | order(_createdAt desc) {
_id,
_createdAt,
title,
description,
photo,
"slug": slug.current,
categories[]->{
_id,
title,
"slug": slug.current
},
author->{
_id,
name,
"slug": slug.current,
email,
avatar
}
}`
);
return (
<Grid container spacing={2} columns={12}>
<PostCards posts={posts} />
</Grid>
);
}
fetch 打 API,容易造成 fetch error。client.fetch,讓資料直接由 Server Component 撈取。👉 總結:在 Next.js + Sanity 專案中,如果是 Server Component,不要走 API Route → fetch,直接用 client.fetch 就能避免踩坑。