【问题标题】:Gatsby: Creating Pages from Contentful FieldsGatsby:从内容字段创建页面
【发布时间】:2021-09-02 22:57:57
【问题描述】:

我在 Contentful 上的每篇文章都有一些与之相关的“类别”。例如,一篇帖子可能包含:

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

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

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

幸运的是,我找到了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。为什么没有创建这些页面?

我做错了什么,我该如何解决?这如何概括为我的三个“类别”?

【问题讨论】:

  • 你能调试你的tags数组吗?
  • @FerranBuireu 我该怎么做?我试过console.log(tags),但显示为undefined。这是在进行构建时。之后我不知道如何调试单个变量。
  • 那么你不能从undefined变量创建页面。 tools 里面有什么?
  • @FerranBuireu,对于每个帖子,工具都是一个字符串数组,例如["R", "Python", "Wordpress"] 我的帖子顶部包含一个示例。
  • 您的代码看起来不错,因为tags 应该用tools 填充。输出是什么:tags.forEach(tag =&gt; {console.log(tag);createPage({path:`/tags/${_.kebabCase(tag)}/`,component: tagTemplate,context: {tag},});

标签: reactjs gatsby contentful


【解决方案1】:

根据你在cmets上说的:

我试过console.log(tags),但显示为undefined

我做到了,它只是一个空白区域。这是否意味着tags 中什么都没有?

您的联系函数看起来不错,该方法很好,因为您将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)

【讨论】:

  • 这行得通!除了有一个问题。它不是单独为weavingcharcoalweb-design 创建页面,而是创建这样的页面:http://localhost:8000/tags/weaving-charcoal-web-design/,合而为一。
  • 如果其余标签有效,则每个帖子的数据结构都不同,并且循环不会生成相同的数组结构(即:["a", ["b","c","d"]] 而不是["a", "b", "c","d"]。检查获取的数据或添加一个 Codesandbox
  • 在这种情况下,使用toolNodes.map(toolNode =&gt; tags.push(...toolNode.tools);
  • 非常感谢!!这完美无缺。如果我可以问最后一个问题,这个tags 数组是全局存储的吗?我可以在另一个页面上引用它以列出所有tools 还是不可能?
  • 另外,这仅在我初始化一个名为tools 的空数组时有效。我猜const toolNodes = data.portfolio.nodes; 包含所有节点,那么它是如何分隔一个名为tools 的节点?
猜你喜欢
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 2014-04-13
  • 1970-01-01
  • 2021-04-01
  • 2018-10-27
  • 2019-12-07
相关资源
最近更新 更多