Sanity x Next.js 撈取 Post 資料踩坑紀錄

2025/08/19

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

撈post資料出現錯誤

build error

錯誤範例

下面這段程式碼是直接用 fetch 呼叫 /api/posts API:

tsx
// 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。

tsx
// 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>
  );
}

結論

  • 錯誤原因:RSC 中用原生 fetch 打 API,容易造成 fetch error。
  • 解法:改用 Sanity 的 client.fetch,讓資料直接由 Server Component 撈取。

👉 總結:在 Next.js + Sanity 專案中,如果是 Server Component,不要走 API Route → fetch,直接用 client.fetch 就能避免踩坑。


這篇文章有幫助嗎?