Отображение содержимого каталога (файлы разметки) в Гэтсби с помощью graphql - PullRequest
0 голосов
/ 06 февраля 2019

Я использую стек Gatsby / Netlify CMS и пытаюсь отобразить содержимое файла уценки на главной странице.Например, у меня есть каталог в src / pages / experience, в котором отображаются все файлы уценки опыта.

Итак, используя graphql, у меня действительно работает запрос:

{
        allMarkdownRemark(
         limit: 3,
         sort: { order: DESC, fields: [frontmatter___date] },
         filter: { fileAbsolutePath: { regex: "/(experience)/" } }
       ) {
           edges {
             node {
               id
               frontmatter {
                 title
                 company_role
                 location
                 work_from
                 work_to
                 tags
               }
               excerpt
             }
           }
         }
     }

Однако, при запуске его на странице моего компонента отображается × TypeError: Невозможно прочитать свойство 'allMarkdownRemark' с неопределенным значением

Однако после ввода этого значения до возврата:

if (!data) { return null };

Ошибка исчезает, но всяраздел исчезает.Вот оно ниже:

const Experience = ({data}) => {

return (

    <div id="experience" className="section accent">
              <div className="w-container">
                  <div className="section-title-group">
                    <Link to="#experience"><h2 className="section-heading centered">Experience</h2></Link>
                  </div>
              <div className="columns w-row">
                     {data.allMarkdownRemark.edges.map(({node}) => (
                        <div className="column-2 w-col w-col-4 w-col-stack" key={node.id}>
                            <div className="text-block"><strong>{node.frontmatter.title}</strong></div>
                            <div className="text-block-4">{node.frontmatter.company_role}</div>
                            <div className="text-block-4">{node.frontmatter.location}</div>
                            <div className="text-block-3">{node.frontmatter.work_from} – {node.frontmatter.work_to}</div>
                            <p className="paragraph">{node.frontmatter.excerpt}</p>
                            <div className="skill-div">{node.frontmatter.tags}</div>
                        </div>
                     ))} 
              </div>
          </div>
      </div>
)}

export default Experience

В gatsby-config-js я добавил разрешение файловой системы gatsby-source отдельно от / src / posts в / src / pages, где каталогом опыта является src /страницы / опыт.

Обновление: 2/7/2019 Вот файл gatsby-config-js:

module.exports = {
  siteMetadata: {
    title: `Howard Tibbs Portfolio`,
    description: `This is a barebones template for my portfolio site`,
    author: `Howard Tibbs III`,
    createdAt: 2019
  },
    plugins: [
      `gatsby-plugin-react-helmet`,
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          name: `images`,
          path: `${__dirname}/src/images`,
          },
      },
      {
        resolve: 'gatsby-transformer-remark',
        options: {
          plugins: [
            {
              resolve: 'gatsby-remark-images',
            },
          ],
        },
      },
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          name: `posts`,
          path: `${__dirname}/src/posts`,
          },
      },
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          name: `pages`,
          path: `${__dirname}/src/pages`,
          },
      },
        `gatsby-plugin-netlify-cms`,
        `gatsby-plugin-sharp`,
        {
          resolve: `gatsby-plugin-manifest`,
          options: {
            name: `gatsby-starter-default`,
            short_name: `starter`,
            start_url: `/`,
            background_color: `#663399`,
            theme_color: `#663399`,
            display: `minimal-ui`,
            icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
          },
        },
        `gatsby-transformer-sharp`
    ],
  }

Мне кажется, что где-то в gatsby-node-jsЯ не создавал экземпляр, чтобы сделать что-то с этим запросом типа.

const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')

const PostTemplate = path.resolve('./src/templates/post-template.js')
const BlogTemplate = path.resolve('./src/templates/blog-template.js')

exports.onCreateNode = ({ node, getNode, actions }) => {
    const { createNodeField } = actions
    if (node.internal.type === 'MarkdownRemark') {
        const slug = createFilePath({ node, getNode, basePath: 'posts' })
    createNodeField({
        node,
        name: 'slug',
        value: slug,
    })

}
}

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

const { createPage } = actions
const result = await graphql(`
    {
        allMarkdownRemark (limit: 1000) {
          edges {
            node {
              fields {
                slug
              }

            }
          }
        }
      }
`)

const posts = result.data.allMarkdownRemark.edges

posts.forEach(({ node: post }) => {
    createPage({
        path: `posts${post.fields.slug}`,
        component: PostTemplate,
        context: {
            slug: post.fields.slug,
        },
    })
})

const postsPerPage = 2
const totalPages = Math.ceil(posts.length / postsPerPage)

Array.from({ length: totalPages }).forEach((_, index) => {
    const currentPage = index + 1
    const isFirstPage = index === 0
    const isLastPage = currentPage === totalPages

    createPage({
        path: isFirstPage ? '/blog' : `/blog/${currentPage}`,
        component: BlogTemplate,
        context: {
            limit: postsPerPage,
            skip: index * postsPerPage,
            isFirstPage,
            isLastPage,
            currentPage,
            totalPages,
        },
    })
})
}

Хотели бы узнать, смог ли кто-нибудь получить что-то похожее на работу?Я очень признателен за вашу помощь.


Обновление: 2/6/2019

Так что некоторые изменения были внесены в мой код с pageQuery в StaticQuery и, к сожалению, он до сих пор не 'это не работает, но я верю, что он идет в правильном направлении:

export default() => (

    <div id="experience" className="section accent">
              <div className="w-container">
                  <div className="section-title-group">
                    <Link to="#experience"><h2 className="section-heading centered">Experience</h2></Link>
                  </div>
              <div className="columns w-row">
              <StaticQuery
              query={graphql`
                  query ExperienceQuery {
                      allMarkdownRemark(
                       limit: 2,
                       sort: { order: DESC, fields: [frontmatter___date]},
                       filter: {fileAbsolutePath: {regex: "/(experience)/"}}
                     ) {
                         edges {
                           node {
                             id
                             frontmatter {
                               title
                               company_role
                               location
                               work_from
                               work_to
                               tags
                             }
                             excerpt
                           }
                         }
                       }
                   }

              `}
              render={data => (
                  <div className="column-2 w-col w-col-4 w-col-stack" key={data.allMarkdownRemark.id}>
                  <div className="text-block"><strong>{data.allMarkdownRemark.frontmatter.title}</strong></div>
                  <div className="text-block-4">{data.allMarkdownRemark.frontmatter.company_role}</div>
                  <div className="text-block-4">{data.allMarkdownRemark.frontmatter.location}</div>
                  <div className="text-block-3">{data.allMarkdownRemark.frontmatter.work_from} – {data.allMarkdownRemark.frontmatter.work_to}</div>
                  <p className="paragraph">{data.allMarkdownRemark.frontmatter.excerpt}</p>
                  <div className="skill-div">{data.allMarkdownRemark.frontmatter.tags}</div>
                  </div>
              )}
              />
              </div>
          </div>
      </div>
);

Я получаю эту ошибку TypeError: Невозможно прочитать свойство 'title' из неопределенного

Так что я пытаюсь выполнить этоэтот экземпляр через этот раздел.Конечно, это заполнитель, но я собираюсь заменить этот заполнитель содержимым каждой уценки. Опыт Snip


Обновление: 2/7/2019

Так что без изменений сегодня, но хотел опубликовать несколько полей, чтобы получитьлучшая перспектива того, что я пытаюсь сделать.Это файл config.yml из NetlifyCMS, где он отображает коллекции.Это то, что я выполняю (Примечание: тестовый репозиторий просто для просмотра действующей CMS, я постараюсь изменить):

backend:
  name: test-repo
  branch: master

media_folder: static/images
public_folder: /images

display_url: https://gatsby-netlify-cms-example.netlify.com/

# This line should *not* be indented
publish_mode: editorial_workflow

collections:

  - name: "experience"
    label: "Experience"
    folder: "experience"
    create: true
    fields:
        - { name: "title", label: "Company Title", widget: "string" }
        - { name: "company_role", label: "Position Title", widget: "string" }
        - { name: "location", label: "Location", widget: "string" }
        - { name: "work_from", label: "From", widget: "date", format: "MMM YYYY" }
        - { name: "work_to", label: "To", default: "Present", widget: "date", format: "MMM YYYY" }
        - { name: "description", label: "Description", widget: "text" }
        - { name: "tags", label: "Skills Tags", widget: "select", multiple: "true", 
              options: ["ReactJS", "NodeJS", "HTML", "CSS", "Sass", "PHP", "Typescript", "Joomla", "CMS Made Simple"] }


  - name: "blog"
    label: "Blog"
    folder: "blog"
    create: true
    slug: "{{year}}-{{month}}-{{day}}_{{slug}}"
    fields:
      - { name: path, label: Path }
      - { label: "Image", name: "image", widget: "image" }
      - { name: title, label: Title }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - {label: "Category", name: "category", widget: "string"}
      - { name: "body", label: "body", widget: markdown }
      - { name: tags, label: Tags, widget: list }


  - name: "projects"
    label: "Projects"
    folder: "projects"
    create: true
    fields:
      - { name: date, label: Date, widget: date }
      - {label: "Category", name: "category", widget: "string"}
      - { name: title, label: Title }
      - { label: "Image", name: "image", widget: "image" }
      - { label: "Description", name: "description", widget: "text" }
      - { name: body, label: "Details", widget: markdown }
      - { name: tags, label: Tags, widget: list}


  - name: "about"
    label: "About"
    folder: "src/pages/about"
    create: false
    slug: "{{slug}}"
    fields:
      - {
          label: "Content Type",
          name: "contentType",
          widget: "hidden",
          default: "about",
        }
      - { label: "Path", name: "path", widget: "hidden", default: "/about" }
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Body", name: "body", widget: "markdown" }

А для примера страницы уценки это будетформат для поиска в разделе опыта, потому что, как вы видите на картинке, он отображается через контейнер:

---
title: Test Company
company_role: Test Role
location: Anytown, USA
work_from: January, 2020
work_to: January, 2020
tags: Test, Customer Service
---

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

Обновление: 2/8/2019

У меня есть некоторые обновления с кодом, приведенным ниже, но прежде чем я углублюсь в это, вот несколько изображений того, чего я хочу достичь.Это заполнители, которые я собираюсь заменить реальными данными.Это для каждого раздела:

Snip полного опыта

Snip проектов

Snip блога

Я запустил код, предоставленный @staypuftman в ответе ниже, и обнаружил эту ошибку:

"gatsby-node.js" вашего сайта создал страницу скомпонент, который не существует.

Я добавил код в дополнение к тому, что уже было там, и он обработал эту ошибку.Это то, что я первоначально думал, что произойдет, и причина, по которой я хотел использовать StaticQuery независимо.На самом деле это была основная проблема, с которой я столкнулся с документацией и начальными репозиториями, никто не создавал несколько переменных в node.js.

Я также пробовал ревизию из @DerekNguyen, которая выглядела так:

import React from "react"
import { Link, graphql, StaticQuery } from "gatsby"



export default(data) => (

        <div id="experience" className="section accent">
                  <div className="w-container">
                      <div className="section-title-group">
                        <Link to="#experience"><h2 className="section-heading centered">Experience</h2></Link>
                      </div>
                  <div className="columns w-row">
                  <StaticQuery
                  query={graphql`
                      query ExperienceQuery {
                          allMarkdownRemark(
                           limit: 2,
                           sort: { order: DESC, fields: [frontmatter___date]},
                           filter: {fileAbsolutePath: {regex: "/(experience)/"}}
                         ) {
                             edges {
                               node {
                                 id
                                 frontmatter {
                                   title
                                   company_role
                                   location
                                   work_from
                                   work_to
                                   tags
                                 }
                                 excerpt
                               }
                             }
                           }
                       }

                  `}
                  render={data.allMarkdownRemark.edges.map(({ node }) => (
                      <div className="column-2 w-col w-col-4 w-col-stack" key={node.id}>
                      <div className="text-block"><strong>{node.frontmatter.title}</strong></div>
                      <div className="text-block-4">{node.frontmatter.company_role}</div>
                      <div className="text-block-4">{node.frontmatter.location}</div>
                      <div className="text-block-3">{node.frontmatter.work_from} – {node.frontmatter.work_to}</div>
                      <p className="paragraph">{node.frontmatter.excerpt}</p>
                      <div className="skill-div">{node.frontmatter.tags}</div>
                      </div>
                  ))}
                  />
                  </div>
              </div>
          </div>
);

Однако это также привело к ошибке:

TypeError: Невозможно прочитать 'края' свойства неопределенного

Все еще работает над этим, ноЯ думаю, что это приближается к решению.Имейте в виду, я также должен был бы создать его для других переменных.


Обновление: 2/10/2019

Для тех, кто хочет увидеть, какЯ создал сайт, используя gatsby-starter, вот он ниже:

Мое портфолио

1 Ответ

0 голосов
/ 08 февраля 2019

gastby-node.js используется, когда у вас есть куча страниц, которые должны быть в /pages/{variable-here}/.Гэтсби использует gatsby-node.js для запуска запроса GraphQL к вашему источнику данных (в данном случае Netlify CMS) и получает весь необходимый контент на основе вашего конкретного запроса GraphQL.

Затем он динамически формирует X страниц, используя компонент в вашем проекте.Сколько страниц он создает, зависит от того, что он находит в удаленном источнике данных.Как они выглядят, зависит от того, какой компонент вы указали.Подробнее об этом читайте в учебнике Gatsby .

Staticquery, который используется для получения одноразовых данных в компоненты, а не для создания страниц из источника данных.Это очень полезно, но не то, что я думаю, что вы пытаетесь сделать.Подробнее об этом читайте на сайте Gatsby .

Исходя из всего этого и того, что вы предоставили выше, я думаю, что ваш gatsby-node.js должен выглядеть так:

// Give Node access to path
const path = require('path')

// Leverages node's createPages capabilities
exports.createPages = async ({ graphql, actions }) => {

  // Destructures createPage from redux actions, you'll use this in a minute
  const { createPage } = actions

  // Make your query
  const allExperiencePages = await graphql(`
    { 
      allMarkdownRemark(limit: 1000) {
        edges {
          node {
            id
            frontmatter {
              title
              company_role
              location
              work_from
              work_to
              tags
            }
            excerpt
          }  
        }
      }
    }
  `)

  // gatsby structures allExperiencePages into an object you can loop through
  // The documentation isn't great but the 'data' property contains what you're looking for
  // Run a forEach with a callback parameter that contains each page's data
  allExperiencePages.data.allMarkdownRemark.edges.forEach( page => {

    // Make individual pages with createPage variable you made earlier
    // The 'path' needs to match where you want the pages to be when your site builds
    // 'conponent' is what Gatsby will use to build the page
    // 'context' is the data that the component will receive when you `gatsby build`
    createPage({
      path: `/pages/${page.node.title}/`,
      component: path.resolve('src/components/Experience'),
      context: {
        id: page.node.id,
        title: page.node.frontmatter.title,
        company_role: page.node.frontmatter.company_role,
        location: page.node.frontmatter.location,
        work_from: page.node.frontmatter.work_from,
        work_to: page.node.frontmatter.work_to,
        tags: page.node.frontmatter.tags,
        excerpt: page.node.excerpt
      }
    })
  }) 

}

Одного этого может быть недостаточно для создания страницы!Все зависит от того, что происходит с компонентом, указанным в компонентной части createPage файла gatsby-node.js.

...