Sanity x Next.js 撈取 Post 資料踩坑紀錄
2025/08/19
最近在做 Sanity + Next.js 專案時,遇到一個奇怪的問題: 用 RSC (React Server Component) 搭配原生 fetch 來撈文章資料,程式碼看起來完全沒毛病,但實際卻會拋出 fetch error。

撈post資料出現錯誤

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