在尝试为类别或标签构建模板页面时,我对 gatsby-node 的误解是什么?

What am I misunderstanding in gatsby-node when trying to build a template page for categories or tags?

尝试学习 Gatsby 在为类别构建分页页面时,我很困惑自己做错了什么。如果 post 的类别是从以下内容的前言创建的:

---
date: '2017-08-10'
title: 'Sweet Pandas Eating Sweets'
slug: 'sweet-pandas-eating-sweets'
description: 'Something different to post'
category: ['sweet', 'yep', 'two']
tags: ['3', '2']
---

在我的 gatsby-node.js 我没有任何问题(或者我应该说抛出的问题)单 post 生成但控制台显示:

Failed to load resource: the server responded with a status of 404 (Not Found)

单击类别而不是单击 <Link> 转到单个 post 时,文件:

exports.createPages = async ({ actions, graphql }) => {
  const { data } = await graphql(`
    query {
      allMdx(sort: { fields: frontmatter___date, order: DESC }) {
        edges {
          node {
            id
            frontmatter {
              title
              slug
              tags
              category
              date
            }
          }
        }
      }
    }
  `)

  if (data.errors) {
    console.error(data.errors)
    throw data.errors
  }

  // const tagSet = new Set()
  // const categorySet = new Set()

  data.allMdx.edges.map(edge => {
    const slug = edge.node.frontmatter.slug
    const id = edge.node.id
    actions.createPage({
      path: slug,
      component: require.resolve(`./src/templates/singlePost.js`),
      context: { id },
    })
  })

  const postPerPage = 3
  const numPages = Math.ceil(data.allMdx.edges.length / postPerPage)
  Array.from({ length: numPages }).forEach((_, i) => {
    actions.createPage({
      path: i === 0 ? `/` : `/${i + 1}`,
      component: require.resolve(`./src/templates/category.js`),
      context: {
        limit: postPerPage,
        skip: i * postPerPage,
        numPages,
        currentPage: i + 1,
      },
    })
  })
}

并在 templates/category.js 中:

import React from 'react'
import { graphql } from 'gatsby'

// Components
import Layout from '../components/Layout'

const category = ({ location, pageContext, data }) => {
  const { currentPage, numPages } = pageContext
  const isFirst = currentPage === 1
  const isLast = currentPage === numPages
  const prevPage = currentPage - 1 === 1 ? '/' : `/${currentPage - 1}`
  const nextPage = `/${currentPage + 1}`
  const posts = data.allMdx.edges

  console.log('data', data)
  return (
    <>
      <Layout>categories</Layout>
    </>
  )
}

export const pageQuery = graphql`
  query CategoryQuery($id: String!, $skip: Int!, $limit: Int!) {
    allMdx(
      sort: { fields: frontmatter___date, order: DESC }
      skip: $skip
      limit: $limit
      filter: { frontmatter: { category: { eq: $id } } }
    ) {
      edges {
        node {
          id
          frontmatter {
            title
            category
            date
            description
            slug
          }
        }
      }
    }
  }
`

export default category

在 GraphiQL 中,我的两个查询都有效,示例仅针对一个类别进行过滤:

{
"id":"two"
}

查询:

query CategoryQuery($id: String!) {
  allMdx(
    sort: {fields: frontmatter___date, order: DESC}
    filter: {frontmatter: {category: {eq: $id}}}
  ) {
    edges {
      node {
        id
        frontmatter {
          title
          category
          date
          description
          slug
        }
      }
    }
  }
}

研究:

为什么当我单击 post 中的类别时,如果我将其添加到 header 中,它会转到 404 页面并指示 /category 尚无页面?

编辑:

删除了正在发生的事情和问题的沙箱:

尝试将节点从 id 更改为 slug,结果相同:

  tagsQuery.data.allMdx.edges.forEach(edge => {
    const slug = edge.node.frontmatter.slug
    actions.createPage({
      path: `category/${slug}`,
      component: require.resolve(`./src/templates/Category.js`),
      context: { slug },
    })
  })

来自 404 页面,在页面下它显示:

/category/undefined
/404/
/
/404.html
/post-slug
/post-slug

有几件事可能会导致问题:

  • 您的 templates/category 部分必须大写:

      const Category = ({ location, pageContext, data }) => {
      const { currentPage, numPages } = pageContext
      const isFirst = currentPage === 1
      const isLast = currentPage === numPages
      const prevPage = currentPage - 1 === 1 ? '/' : `/${currentPage - 1}`
      const nextPage = `/${currentPage + 1}`
      const posts = data.allMdx.edges
    
      console.log('data', data)
      return (
        <>
          <Layout>categories</Layout>
        </>
      )
    }
    

    否则,React 将无法推断和创建有效组件。

  • 在对类别或标签进行分页之前,我会尝试创建一个循序渐进的方法,成功创建类别模板。您正在重复使用相同的查询来创建帖子和类别,但您永远不会循环创建类别。我会将逻辑分成两个单独的 GraphQL 查询:

      exports.createPages = async ({ actions, graphql }) => {
        const postsQuery = await graphql(`
          query {
            allMdx(sort: { fields: frontmatter___date, order: DESC }) {
              edges {
                node {
                  id
                  frontmatter {
                    title
                    slug
                    tags
                    category
                    date
                  }
                }
              }
            }
          }
        `)
    
        const tagsQuery = await graphql(`
          query {
            allMdx(sort: { fields: frontmatter___date, order: DESC }) {
              edges {
                node {
                  id
                  frontmatter {
                    tags
                    category
                  }
                }
              }
            }
          }
        `)
    
    
        if (postsQuery.data.errors || tagsQuery.data.errors) {
          console.error(data.errors)
          throw data.errors
        }
    
        // const tagSet = new Set()
        // const categorySet = new Set()
    
        tagsQuery.data.allMdx.edges.map(edge => {
          const slug = edge.node.frontmatter.slug
          const id = edge.node.id
          actions.createPage({
            path: slug, // or `category/${slug}`
            component: require.resolve(`./src/templates/category.js`),
            context: { id },
          })
        })
    
    
        postsQuery.data.allMdx.edges.map(edge => {
          const slug = edge.node.frontmatter.slug
          const id = edge.node.id
          actions.createPage({
            path: slug,
            component: require.resolve(`./src/templates/singlePost.js`),
            context: { id },
          })
        })
        /*
        const postPerPage = 3
        const numPages = Math.ceil(data.allMdx.edges.length / postPerPage)
        Array.from({ length: numPages }).forEach((_, i) => {
          actions.createPage({
            path: i === 0 ? `/` : `/${i + 1}`,
            component: require.resolve(`./src/templates/category.js`),
            context: {
              limit: postPerPage,
              skip: i * postPerPage,
              numPages,
              currentPage: i + 1,
            },
          })
        })*/
      }
    

    要检查已创建的页面,您可以随时在 gatsby develop (localhost:8000/someOddString) 模式下查找 404 页面,默认情况下,它会打印所有已创建的页面。

在 GraphiQL 中进一步研究和测试后,我在 allMDX 中找到了 distinct,我能够查询 frontmatter 类别或标签:

foo.mdx 前言:

---
date: '2017-08-10'
title: 'Sweet Pandas Eating Sweets'
slug: 'sweet-pandas-eating-sweets'
description: 'Something different to post'
category: ['sweet', 'yep', 'two']
---

盖茨比-node.js:

exports.createPages = async ({ actions, graphql }) => {
  const catsQuery = await graphql(`
    query {
      allMdx(filter: { fileAbsolutePath: { regex: "/content/" } }) {
        distinct(field: frontmatter___category)
      }
    }
  `)

  catsQuery.data.allMdx.distinct.forEach(category => {
    actions.createPage({
      path: `/category/${category}`,
      component: require.resolve(`./src/templates/category.js`),
      context: { category },
    })
  })
}