Gatsby:从内容丰富的字段创建页面

Gatsby: Creating Pages from Contentful Fields

我在 Contentful 上的每个 post 都有一些相关联的 'categories'。例如,一个 post 可能包含:

major: "HCD"
year: "1st Year"
tools: ["R", "Python", "Wordpress"]

这些只是具有这些值的名为 majoryear 等的字段,但它们被视为单独的类别。 在网站上,它们显示如下:

我正在尝试为每个类别创建一个页面。例如,如果用户单击 Photoshop,他们应该被带到页面 tags/photoshop,并且应该列出所有包含该标签的 post。

幸运的是,我能够找到 this guide 来帮助我完成这项工作。但是,该指南不适用于内容丰富的数据,因此我在如何执行此操作方面遇到了一些麻烦。我已经创建了 tagsTemplate.jsx,但我一直在创建实际页面。

例如,这是我尝试为 tools 创建页面所做的:

我的 gatsby-node.js 文件如下所示:

const path = require(`path`)
const _ = require('lodash');

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type contentfulPortfolioDescriptionTextNode implements Node {
      description: String
      major: String
      author: String
      tools: [String]
      files: [ContentfulAsset]
      contact: String
    }
    type ContentfulPortfolio implements Node {
      description: contentfulPortfolioDescriptionTextNode
      gallery: [ContentfulAsset]
      id: ID!
      name: String!
      related: [ContentfulPortfolio]
      slug: String!
      major: String!
      files: [ContentfulAsset]
      author: String!
      tools: [String]!
      year: String!
      thumbnail: ContentfulAsset
      url: String
      contact: String
    }
  `
  createTypes(typeDefs)
}

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

  return new Promise((resolve, reject) => {
    graphql(`
      {
        portfolio: allContentfulPortfolio {
          nodes {
            slug
            tools
          }
        }
      }
    `).then(({ errors, data }) => {
      if (errors) {
        reject(errors)
      }

      if (data && data.portfolio) {
        const component = path.resolve("./src/templates/portfolio-item.jsx")
        data.portfolio.nodes.map(({ slug }) => {
          createPage({
            path: `/${slug}`,
            component,
            context: { slug },
          })
        })
      }
       
      const tools = data.portfolio.nodes.tools;
      const tagTemplate = path.resolve(`src/templates/tagsTemplate.js`);
      let tags = [];
      // Iterate through each post, putting all found tags into `tags`
      tags = tags.concat(tools);
       // Eliminate duplicate tags
      tags = _.uniq(tags);
      
       // Make tag pages
       tags.forEach(tag => {
        createPage({
          path: `/tags/${_.kebabCase(tag)}/`,
          component: tagTemplate,
          context: {
            tag
          },
        });
      });
      
      console.log("Created Pages For" + tags)

      resolve()
    })
  })
}

我的tagsTemplate现在是最小的,因为我不知道如何查询数据:

import React from 'react';
import Layout from "../layouts/Layout"

const Tags = ({ data }) => {
  return (
    <Layout>
      <div>Tags</div>
    </Layout>
  );
};

export default Tags;

问题:当我访问我知道存在的标签之一的页面时(例如 photoshop),我收到 404。为什么没有创建这些页面?

我做错了什么,我该如何解决?如何将这概括为我的三个 'categories'?

根据您在评论中所说的:

I tried console.log(tags) but is shows it as undefined

I did that and it is just a blank space. Does that mean there is nothing in tags at all?

您的联系人功能看起来不错,方法很好,因为您将 toolstags 的列表)添加到新数组中以清理它并留下唯一值(uniq).完成后,您将遍历唯一标记并基于该数组创建页面。

也就是说,您的纸牌屋有一些弱点可能会崩溃。您的问题从这一行开始:

const tools = data.portfolio.nodes.tools;

并通过代码传播。

nodes 是一个数组,因此,要获得您应该做的任何值:

const tools = data.portfolio.nodes[0].tools;

获得第一名等等...

由于从未填充 tools,因此其余代码不起作用。

您可以很容易地修复它循环遍历 nodes 并使用类似于以下内容的内容填充您的 tags 数组:

  const toolNodes = data.portfolio.nodes;

  const tagTemplate = path.resolve(`src/templates/tagsTemplate.js`);
  let tags = [];

  // Iterate through each post, putting all found tags into `tags`
  toolNodes.map(toolNode => tags.push(toolNode.tools);
  // if the fetched data is still an array you can do toolNodes.map(toolNode => tags.push(...toolNode.tools);     

   // Eliminate duplicate tags
  tags = _.uniq(tags);
  
   // Make tag pages
   tags.forEach(tag => {
    createPage({
      path: `/tags/${_.kebabCase(tag)}/`,
      component: tagTemplate,
      context: {
        tag
      },
    });
  });
  
  console.log("Created Pages For" + tags)