You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js对接Sanity拉取博客时PortableText报未知块类型错误

报错原因

触发这个报错有三个核心原因:

  • 你使用的新版@portabletext/react组件API和你写的传参方式不兼容:v2版本之后,原来接收富文本内容的content属性改名为value,接收自定义渲染规则的serializers属性改名为components,你传入的projectId、dataset属性组件本身根本不识别,整套自定义配置完全没有生效。
  • 自定义渲染规则的结构不符合新版要求:旧版支持扁平传入h1、li这类渲染函数,新版要求按类型分类配置,块级标题、段落放在block下,列表项放在listItem下,自定义Schema块放在types下,文本标记放在marks下,结构不对时组件找不到对应块的渲染方法,就会抛出块类型为undefined的错误。
  • 数据拉取没有做兜底校验:GROQ查询直接拉取全量blog类型数据,没有过滤content字段为空的条目,也没有判断返回数组是否为空,直接取blogs[0].content很容易拿到undefined值,触发渲染错误。如果Sanity后台的富文本里存了没有_type属性的异常块、或者配置了自定义Schema块(比如图片、代码块、引用卡片)但没写对应渲染规则,也会触发同类报错。
修复步骤
  1. 先确认安装的PortableText依赖是官方最新的@portabletext/react,卸载旧的@sanity/block-content-to-react避免版本冲突。
  2. 调整组件传参和自定义渲染配置的结构,匹配新版API要求。
  3. 给GROQ查询加字段投影和过滤,给渲染逻辑加空值兜底,避免异常数据触发报错。
  4. 检查Sanity博客Schema中content字段用到的所有自定义块类型,在配置的types节点下补全对应的渲染组件。
修复后的参考代码
// 页面组件部分
import { PortableText } from '@portabletext/react'

// 按新版要求定义富文本渲染组件
const portableTextComponents = {
  block: {
    // 自定义h1渲染,其余块级标签如果不需要特殊样式可以不写,走默认渲染
    h1: ({ children }) => <h1 style={{ color: "red" }}>{children}</h1>,
  },
  listItem: {
    // 自定义无序列表、有序列表的列表项样式
    bullet: ({ children }) => <li className="special-list-item">{children}</li>,
    number: ({ children }) => <li className="special-list-item">{children}</li>,
  },
  types: {
    // 这里补全所有自定义块的渲染逻辑,比如Sanity自带的图片类型:
    // image: ({ value }) => <img src={/* 自行拼接Sanity图片地址 */} alt={value.alt || ''} />
    // 没有自定义块时保留空对象即可,避免类型查找报错
  }
}

export default function BlogPage({ blogs = [] }) {
  return (
    <div className="blog-content">
      {/* 加空值兜底,避免访问不存在的属性报错 */}
      {blogs?.[0]?.content ? (
        <PortableText
          value={blogs[0].content}
          components={portableTextComponents}
        />
      ) : (
        <p>暂无博客内容</p>
      )}
    </div>
  )
}

// getServerSideProps部分
export async function getServerSideProps() {
  const client = createClient({
    projectId: 'oeqragbg',
    dataset: 'production',
    useCdn: false,
    apiVersion: '2024-01-01' // 必须指定API版本,避免返回数据格式异常
  });
 
  // GROQ查询加过滤和字段投影,只拉取需要的有效数据
  const query = `*[_type == "blog" && defined(content)]{
    _id,
    title,
    content
  }`;
  const blogs = await client.fetch(query);

  return {
    props: {
      blogs: blogs || []
    }
  }
}

内容的提问来源于stack exchange,提问作者Sushant Bansode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:02:00