Gatsby通过GraphQL获取Prismic数据读document报错解决方法
问题原因与修复方案
报错根因
触发Cannot read properties of undefined (reading 'document')的核心原因有两个:
- GraphQL返回的
links字段是数组类型:Prismic中设置为可重复的内容关系/分组字段会以数组结构返回,你没有先遍历links数组,直接访问post.data.links.blog,相当于在数组对象上取blog属性,得到的值为undefined,再往下访问document自然会抛出类型错误。 - 缺少空值兜底逻辑:部分Prismic条目可能未填写关联内容,直接做深层属性访问很容易碰到空值触发报错。
第一步:优化GraphQL查询
可以先在Gatsby本地GraphQL调试面板(默认地址http://localhost:8000/___graphql)验证字段结构,建议给关联文档节点增加__typename字段,方便后续区分不同类型的关联文档:
{ allPrismicLastPosts { nodes { data { blog_title { text } blog_paragraph { text } links { blog { document { # 新增该字段用于区分关联文档类型 __typename ... on PrismicBlog { data { post_img { url } post_title { text } post_paragraph { text } tag } } ... on PrismicCulture { data { tag culture_image { url } culture_paragraph { text } culture_title { text } } } } } } } } } }
第二步:修正组件渲染逻辑
需要先遍历links数组,再读取每个链接项下的关联文档,同时通过可选链?.做空值兜底,最后根据__typename判断关联文档类型,读取对应字段渲染即可:
{docs.nodes.map((post)=> ( <Posts> <PostsTitle> {post.data.blog_title.text} </PostsTitle> <PostsParagraph> {post.data.blog_paragraph.text} </PostsParagraph> {/* 先遍历links数组,加可选链避免空值报错 */} {post.data.links?.map((linkItem, index) => { const relatedDoc = linkItem?.blog?.document // 若当前条目未关联文档,直接跳过渲染 if (!relatedDoc) return null // 按文档类型匹配对应字段 const isBlogType = relatedDoc.__typename === 'PrismicBlog' const postTitle = isBlogType ? relatedDoc.data.post_title.text : relatedDoc.data.culture_title.text const postContent = isBlogType ? relatedDoc.data.post_paragraph.text : relatedDoc.data.culture_paragraph.text const postCover = isBlogType ? relatedDoc.data.post_img.url : relatedDoc.data.culture_image.url const postTag = relatedDoc.data.tag return ( <GridPosts key={index}> <GridPost> <img src={postCover} alt={postTitle} /> <FlexPost> <PostTitle>{postTitle}</PostTitle> <PostParagraph>{postContent}</PostParagraph> <PostTag>{postTag}</PostTag> </FlexPost> </GridPost> </GridPosts> ) })} </Posts> ))}
Prismic内联片段数据获取说明
Gatsby + Prismic的GraphQL层中,... on PrismicBlog这类内联片段返回的内容会直接挂在对应的document节点下,不需要额外做格式解析,只需要注意两点:
- 查询时给关联文档节点加上
__typename字段,用来区分不同类型的关联内容 - 拿到
document对象后,先判断__typename的值,匹配到对应内容类型后再读取该类型下的字段即可 - 所有Prismic返回的嵌套字段,都建议加可选链做兜底,避免单条内容字段缺失导致整个页面崩溃
内容的提问来源于stack exchange,提问作者Jaacoubi
相关产品推荐
相关产品推荐

