HygraphCMS数据获取报错:TypeError无法读取postsConnection属性
从HygraphCMS获取数据时出现
TypeError: Cannot read properties of undefined (reading 'postsConnection') 我花了好几个小时尝试解决从HygraphCMS获取数据的问题,但毫无进展。运行代码时抛出如下错误,但直接在GraphQL中执行查询语句能得到正常结果,恳请帮忙排查问题。
相关代码
import { request } from "graphql-request"; import Link from "next/link"; import { useState } from "react"; import useSWR from "swr"; const fetcher = (endpoint, query, variables) => request(endpoint, query, variables); export const getStaticProps = async () => { const data = await fetcher( "https://api-eu-central-1-shared-euc1-02.hygraph.com/v2/clh4qcnhy5i5r01um1qbo28dj/master", `query getPosts { postsConnection(orderBy: date_DESC, first: 2, skip: 0) { edges { node { id title date slug description author { name } } } pageInfo { hasNextPage hasPreviousPage pageSize } } }`, ); return { props: { posts: data, }, }; }; export default function BlogPage({ posts }) { console.log(posts); const [searchValue, setSearchValue] = useState(""); const [skip, setSkip] = useState(0); const { data, error } = useSWR( [ "https://api-eu-central-1-shared-euc1-02.hygraph.com/v2/clh4qcnhy5i5r01um1qbo28dj/master", `query getPosts($searchValue: String $skip: Int) { postsConnection(orderBy: date_DESC, where: {title_contains: $searchValue}, first: 2, skip: $skip) { edges { node { id title date slug description id author { name } } } pageInfo{ hasNextPage hasPreviousPage pageSize } } } `, searchValue, skip, ], (endpoint, query) => fetcher(endpoint, query, { searchValue, skip }), { initialData: posts, revalidateOnFocus: true }, ); if (error) { return ( <div> <h2>There was an error with the data fetching</h2> </div> ); } return ( <div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-0"> <h1 className="text-5xl text-gray-600 font-serif mb-6 font-bold">The Blog</h1> <div> <input type="text" value={searchValue} placeholder="Search blog posts" className="focus:outline-none mb-6 focus:ring-2 focus:ring-gray-900 w-full rounded-lg border h-10 pl-4 text-lg text-gray-800 border-gray-200" onChange={(event) => setSearchValue(event.target.value)} /> </div> <div> {data.postsConnection?.edges?.map((post) => ( <div key={post.node.slug} className="grid grid-cols-1 md:grid-cols-4 py-6"> <div className="mb-2 md:mb-0 md:col-span-1"> <p className="text-gray-600 text-sm">{new Date(post.node.date).toDateString()}</p> </div> <div className="md:col-span-3"> <Link href={`/blog/${post.node.slug}`}> <a className="text-2xl font-semibold text-gray-900 hover:text-gray-700 transition-colors duration-300"> {post.node.title} </a> </Link> <p className="text-gray-700 leading-relaxed">{post.node.description}</p> <div className="text-sm text-gray-900 font-semibold mt-1"> {post.node.author.name} </div> </div> </div> ))} </div> <div className="flex space-x-5 justify-center items-center mt-10"> <div> <button onClick={() => { setSkip(skip - 2); }} disabled={!data.postsConnection.pageInfo.hasPreviousPage} className="bg-indigo-700 w-20 text-white px-3 py-1 rounded-md disabled:bg-gray-400 disabled:text-gray-800"> Previous </button> </div> <div> <button onClick={() => { setSkip(skip + 2); }} disabled={!data.postsConnection.pageInfo.hasNextPage} className="bg-indigo-700 w-20 text-white px-3 py-1 rounded-md disabled:bg-gray-400 disabled:text-gray-800"> Next </button> </div> <div className="text-gray-700">Total Pages: {data.postsConnection.pageInfo.pageSize}</div> </div> </div> ); }
错误信息
TypeError: Cannot read properties of undefined (reading 'postsConnection')
错误来源:
Source pages/blog/index.js (105:14) @ BlogPage 103 | </div> 104 | <div> > 105 | {data.postsConnection?.edges?.map((post) => ( | ^ 106 | <div key={post.node.slug} className="grid grid-cols-1 md:grid-cols-4 py-6"> 107 | <div className="mb-2 md:mb-0 md:col-span-1"> 108 | <p className="text-gray-600 text-sm">{new Date(post.node.date).toDateString()}</p>
GraphQL查询结果
getStaticProps的查询结果
{ "data": { "postsConnection": { "edges": [ { "node": { "id": "clh4w8dhkaufl0bw1jux7ek2y", "title": "React Toast Component and Custom Hook using Tailwindcss", "date": "2023-05-01T13:45:00+00:00", "slug": "react-toast-component-and-custom-hook-using-tailwindcss", "description": "Toasts are basically just notifications. When you have a complex application or you need a lot of input", "author": { "name": "HerminioHenriques" } } }, { "node": { "id": "clh4tgvgxac9f0bt92iyuni90", "title": "Dummy markdown post", "date": "2023-05-01T12:26:00+00:00", "slug": "dummy-markdown-post", "description": "How to use markdown language", "author": { "name": "HerminioHenriques" } } }, { "node": { "id": "clh4var6yaqwl0bw1aefk73rc", "title": "Next.js, Typescript and ESLint Starter Configuration", "date": "2023-04-25T17:00:00+00:00", "slug": "nextjs-typescript-and-eslint-starter-configuration", "description": "This blog post will guide you through configuring a new Next.js project, ready to go with Typescript, ESLint and pre-commit checking with Husky", "author": { "name": "HerminioHenriques" } } } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "pageSize": 3 } } } }
组件内查询的结果
{ "data": { "postsConnection": { "edges": [ { "node": { "id": "clh4tgvgxac9f0bt92iyuni90", "title": "Dummy markdown post", "date": "2023-05-01T12:26:00+00:00", "slug": "dummy-markdown-post", "description": "How to use markdown language", "author": { "name": "HerminioHenriques" } } } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "pageSize": 1 } } } }
问题排查与解决
核心原因
- 数据结构不匹配:
getStaticProps返回的posts是{ data: { postsConnection: ... } },但useSWR请求返回的data直接包含postsConnection字段,导致initialData的结构和后续请求返回的结构不一致,触发报错。 - 未处理空值场景:分页按钮和页码显示处直接访问
data.postsConnection.pageInfo,没有做可选链保护,当data为undefined时会直接抛出错误。
解决步骤
1. 修正getStaticProps返回的结构
将getStaticProps中返回的posts改为data.data,让初始数据结构和useSWR请求返回的结构一致:
export const getStaticProps = async () => { const data = await fetcher(/* ... */); return { props: { posts: data.data, // 这里改为data.data }, }; };
2. 给分页相关代码添加可选链保护
在分页按钮和页码显示处添加可选链,避免data为undefined时触发报错:
// Previous按钮 disabled={!data?.postsConnection?.pageInfo?.hasPreviousPage} // Next按钮 disabled={!data?.postsConnection?.pageInfo?.hasNextPage} // 页码显示 <div className="text-gray-700">Total Pages: {data?.postsConnection?.pageInfo?.pageSize}</div>
完成以上修改后,代码就能正确处理初始数据和后续请求数据,避免postsConnection未定义的报错。
内容的提问来源于stack exchange,提问作者Herminio Henriques
相关产品推荐
相关产品推荐

