【问题标题】:Gatsby Create Pages盖茨比创建页面
【发布时间】:2021-01-21 21:49:49
【问题描述】:

我正在尝试创建一个 gatsby 网站,我在其中发布了项目,每个项目都有标签。我遵循了有关创建 gatsby 博客的基本教程,现在正在研究 gatsby 的标签,如其网站上记录的那样。在将变量名从路径更改为 slug 以避免保留字的过程中,我似乎搞砸了,因为我不能再创建博客文章页面,也不能标记页面。每篇文章都包含在一个以文章标题命名的文件夹中,其中包含一个 index.md 文件,用于定义其内容、日期、标签等。

当我尝试运行 gatsby develop 时输出以下错误,

错误 #11323

Your site's "gatsby-node.js" must set the page path when creating a page.

The page object passed to createPage:
{
    "slug": "/an-example-post",
    "component": "C:\\Users\\Monolith\\Documents\\programming\\webdev\\Gatsby-Portfolio\\src\\templates\\post.js",
    "context": {
        "slug": "/an-example-post"
    }
}

我的 gatsby-node.js

const path = require('path');

exports.createPages = ({actions, graphql}) => {
     const {createPage} = actions;

     const postTemplate = path.resolve('src/templates/post.js');
     const tagTemplate = path.resolve("src/templates/tags.js")
     //const postTemplate = require.resolve('src/templates/post.js');
     //const tagTemplate = require.resolve("src/templates/tags.js")
     
     return graphql(`{
        allMarkdownRemark{
            edges{
                node {
                    html
                    id
                    frontmatter{
                        slug
                        title
                    }
                }
            }
        }
    
        tagsGroup: allMarkdownRemark(limit: 2000) {
            group(field: frontmatter___tags) {
              fieldValue
            }
          }

    }`)
    .then(res => {
        if(res.errors){
            return Promise.reject(res.errors);
        }


        
        res.data.allMarkdownRemark.edges.forEach( ({node}) => {
            createPage({
                slug: node.frontmatter.slug,
                component: postTemplate,
                context: {
                    slug:node.frontmatter.slug
                },
            })
        })

          // Extract tag data from query
        const tags = res.data.tagsGroup.group

        // Make tag pages
        tags.forEach(tag => {
            createPage({
                // path: `/tags/${_.kebabCase(tag.fieldValue)}/`,
                slug: `/tags/${(tag.fieldValue)}/`,
                component: tagTemplate,
                context: {
                    tag: tag.fieldValue,
                },
            })
        })

    }) 
}

如前所述,我担心作为保留字的路径变量可能是一个问题,但我进一步使用它而不是省略它,所以现在它一直保留。

示例 post.js

import React from 'react';
import { graphql } from 'gatsby';
import Layout from "../components/layout"

export default function Template({data}) {
    const {markdownRemark: post} = data;

    return(
        <Layout>
        <div>
            <h1 className="postTitle">{post.frontmatter.title}</h1>
            <div className="tagGroup">
                {post.frontmatter.tags.map((tag, index) => (
                    <div key={index}>
                        <h2 className = "tagStyle">{tag}</h2>
                    </div>
                ))}
            </div>
            <p>{post.frontmatter.description}</p>
            <p>{post.frontmatter.date}</p>            
            {/* <h2 className="tagStyle">{post.frontmatter.tags + " "}</h2> */}
            <div dangerouslySetInnerHTML={{__html: post.html}} />
        </div>
        </Layout>
    )
}


export const postQuery = graphql`
    #query BlogPostByPath($slug: String!) {
    query($slug: String!) {
        markdownRemark(frontmatter: { slug: {eq: $slug} }) {
            html
            frontmatter {
                slug
                title
                description
                date
                tags
            }
        }
    }
`

tags.js 与 gatsby 的默认值非常相似,只是对内容稍作改动。这是我正在使用的 Graphql 查询。

Tags.propTypes = {
  pageContext: PropTypes.shape({
    tag: PropTypes.string.isRequired,
  }),
  data: PropTypes.shape({
    allMarkdownRemark: PropTypes.shape({
      totalCount: PropTypes.number.isRequired,
      edges: PropTypes.arrayOf(
        PropTypes.shape({
          node: PropTypes.shape({
            frontmatter: PropTypes.shape({
              title: PropTypes.string.isRequired,
           //   slug: PropTypes.string.isRequired,
            }),
            fields: PropTypes.shape({
              slug: PropTypes.string.isRequired,
            }),
          }),
        }).isRequired
      ),
    }),
  }),
}

export default Tags

export const pageQuery = graphql`
  query($tag: String) {
    allMarkdownRemark(
      limit: 2000
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { tags: { in: [$tag] } } }
    ) {
      totalCount
      edges {
        node {
           fields {
             slug
           }
          frontmatter {
            title
          }
        }
      }
    }
  }
`

如果有人有任何信息可以帮助我指明正确的方向,我将不胜感激。我已经浏览了几个小时的 gatsby 文档,但还没有取得实质性进展。

【问题讨论】:

  • " createPage({ // 此页面的路径 - 必填路径:" - 不使用 'path' 变量并不意味着它不能用作道具名称
  • 嗯好的,所以我将请求更改为 createPage({ path: node.frontmatter.slug, component: postTemplate, context: { slug:node.frontmatter.slug}。但错误消息现在显示上下文中的路径和 slug 为空。我不确定我理解你的意思。

标签: javascript node.js graphql gatsby express-graphql


【解决方案1】:

您在上下文中传递了tag,但期待slug

    createPage({
        slug: `/tags/${(tag.fieldValue)}/`,
        component: tagTemplate,
        context: {
            tag: tag.fieldValue,
        },
    })

还有:

   query($slug: String!) {}

上下文是一种将数据传递给组件模板以使用它来过滤数据的方法。理想情况下应该是一个唯一的参数(如slugid 等)。这样,在您的 gatsby-node.js 中,您应该获取所有帖子,按上下文传递一个唯一字段,并在模板中使用该变量来获取每个帖子所需的所有数据。

此外,您必须为您的函数提供path,而不是slug

您应该将createPage 函数更改为:

    createPage({
        path: `/tags/${tag.fieldValue}/`,
        component: tagTemplate,
        context: {
            slug: tag.fieldValue,
        },
    })

请记住,fieldValue 应该是一个 slug(或某种),尽管有不同的命名。

我会推荐阅读 Gatsby 的教程:https://www.gatsbyjs.com/tutorial/part-seven/

【讨论】:

  • 太棒了!非常感谢您的详尽回答。我似乎通过这些更改做了一些事情,并认为这绝对是问题的解决方案。我还为我的 tags.js 发布了错误的最终代码 sn-p。我相信这应该是用于生成标签的查询,但它无法查询 MarkdownRemark 的字段字段,尽管 allMarkdownRemark 似乎是 gatsbyjs 教程中建议的主要方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2019-12-16
  • 2020-07-20
  • 2020-10-16
  • 2019-08-07
  • 1970-01-01
  • 2021-12-14
相关资源
最近更新 更多