在Gatsby中如何将Staticman表单提交筛选至对应页面?
Cannot read property 'edges' of undefined错误 我来帮你排查这个问题——你遇到的这个错误,通常是因为组件在数据加载完成前就尝试访问allReviewsYaml.edges,或者你的页面查询没有正确接收$slug参数、评论数据的fields.slug字段未正确生成,导致查询返回的allReviewsYaml为undefined。下面分步骤帮你解决:
1. 确认页面查询的参数传递是否正确
首先要明确:带变量的GraphQL查询只能用在页面组件中(src/pages下的文件,或通过gatsby-node.js动态生成的页面),StaticQuery不支持变量传递。
如果是通过gatsby-node.js生成动态页面,务必确保在createPage时把slug参数传入context:
// gatsby-node.js 示例代码 exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; // 先获取所有房源数据 const propertyResult = await graphql(` query { allPropertyYaml { edges { node { listing_id } } } } `); // 为每个房源生成详情页 propertyResult.data.allPropertyYaml.edges.forEach(({ node }) => { createPage({ path: `/property/${node.listing_id}`, component: require.resolve("./src/templates/property-review-page.js"), context: { slug: node.listing_id, // 关键:传递slug参数给页面查询 }, }); }); };
如果是src/pages下的动态路由页面(比如[slug].js),Gatsby会自动把URL中的参数作为slug传入查询,这一步无需额外配置。
2. 确保评论YAML文件的fields.slug字段正确生成
你的查询依赖fields.slug来筛选对应房源的评论,所以必须通过gatsby-node.js的onCreateNode API为每个评论文件添加这个字段:
// gatsby-node.js 示例代码 exports.onCreateNode = ({ node, actions, getNode }) => { const { createNodeField } = actions; // 只处理评论YAML节点 if (node.internal.type === "ReviewsYaml") { // 从文件路径中提取listing_id const parentFile = getNode(node.parent); // 你的文件路径是src/data/review/property-[listing_id]/xxx.yml,拆分路径获取房源ID const propertyDir = parentFile.relativePath.split("/")[1]; const listingId = propertyDir.replace("property-", ""); createNodeField({ node, name: "slug", value: listingId, }); } };
这一步如果出错,查询的filter条件会匹配不到任何数据,直接导致allReviewsYaml返回undefined。
3. 在组件中添加空值检查并正确访问数据
Gatsby在构建或客户端渲染时,数据可能还未完全加载,所以必须先做空值判断,再访问edges:
import React from "react"; import { graphql } from "gatsby"; const PropertyReviewPage = ({ data }) => { // 用可选链操作符避免访问undefined属性,也可以用条件判断 const reviews = data.allReviewsYaml?.edges || []; const property = data.property; // 房源数据未加载时显示加载状态 if (!property) { return <div>Loading...</div>; } return ( <div className="property-page"> <h1>房源ID: {property.listing_id}</h1> <p>{property.description}</p> <h2>用户评论</h2> {reviews.length === 0 ? ( <p>暂无评论,快来留下第一条吧~</p> ) : ( reviews.map(({ node }) => ( <div key={`${node.listing_id}-${node.date}`} className="review-card"> <h3>评论人:{node.name}</h3> <p>{node.review}</p> </div> )) )} </div> ); }; // 注意:调整property的类型名称(如果是YAML文件,Gatsby会自动转为驼峰式,比如propertyYaml) export const query = graphql` query($slug: String!) { property: propertyYaml(listing_id: { eq: $slug }) { description listing_id } allReviewsYaml( filter: { fields: { slug: { eq: $slug } } } sort: { fields: date, order: DESC } ) { edges { node { name review listing_id date } } } } `; export default PropertyReviewPage;
4. 验证GraphQL查询的正确性
在GraphiQL中测试时,务必传入和页面context一致的$slug参数(比如{"slug": "123"}),确认查询能返回预期的allReviewsYaml数据。如果查询在GraphiQL中正常,但页面报错,大概率是参数传递或空值检查的问题。
按照以上步骤逐一排查,应该就能解决这个错误了。
内容的提问来源于stack exchange,提问作者user2143548

