Могу ли я передать два объекта в контекст в createPage?

Мой блог будет отображать изображение и имя автора в каждом посте, и для того, чтобы шаблон загружал правильный, мне нужно было бы передать значение через контекст. Дело в том, что $ slug уже является объектом для функции blogPage в gatsby-node.

Что-то вроде этого:

const path = require(`path`)
const _ = require("lodash")

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

  const blogPostTemplate = path.resolve(`src/templates/blogPost.js`)
  const autorPageTemplate = path.resolve(`src/templates/autorPage.js`)
  const tagTemplate = path.resolve(`src/templates/tags.js`)
  const catTemplate = path.resolve(`src/templates/categories.js`)


  const result = await graphql(`
    {
      blogPost: allMarkdownRemark(
        filter: {
          frontmatter: {
            type: {
              eq: "blog-post"
            }
          }
        },
        sort: { 
          order: DESC, 
          fields: [
            frontmatter___date
          ] 
        },
        limit: 1000
      ) {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
      autorPage: allMarkdownRemark(
        filter: {
          frontmatter: {
            type: {
              eq: "autor"
            }
          }
        }
      ) {
        edges {
          node {
            frontmatter {
              name
            }
          }
        }
      }
      tagsGroup: allMarkdownRemark(limit: 2000) {
        group(field: frontmatter___tags) {
          fieldValue
        }
      }
      categoriesGroup: allMarkdownRemark(limit: 2000) {
        group(field: frontmatter___categories) {
          fieldValue
        }
      }
    }
  `)

  // Handle errors
  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

  // Extract blog data from query
  const blogPage = result.data.blogPost

  blogPage.edges.forEach(({ node }) => {
    createPage({
      path: `/blog/${_.kebabCase(node.fields.slug)}/`,
      component: blogPostTemplate,
      context: {
        slug: node.fields.slug, // $slug
        autor: node.frontmatter.autor // $autor - it queries from eachposts frontmatter, which contains autor's name.
      }, 
    })
  })

  // Extract blog data from query
  const autorPage = result.data.autorPage

  autorPage.edges.forEach(({ node }) => {
    createPage({
      path: `/autor/${_.kebabCase(node.frontmatter.name)}/`,
      component: autorPageTemplate,
      context: {
        autor: node.frontmatter.name
      },
    })
  })

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

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

  // Extract categories data from query
  const categories = result.data.categoriesGroup.group

  // Make tag pages
  categories.forEach(category => {
    createPage({
      path: `/categorias/${_.kebabCase(category.fieldValue)}/`,
      component: catTemplate,
      context: {
        category: category.fieldValue,
      },
    })
  })

}

Прямо сейчас мой шаблон сообщений получает только $ slug:

import React from "react"
import { graphq, StaticQuery, Link } from "gatsby"
import Img from "gatsby-image"
import AniLink from "gatsby-plugin-transition-link/AniLink"

import BlogLayout from '../components/layout/BlogLayout'
/*import TextScramble from '../components/TextScramble'*/

import kebabCase from "lodash/kebabCase"

import PostAutor from '../components/postAutor'
import TextScramble from "../components/TextScramble"


const Autoria = ({ 
  data: { 
    allMarkdownRemark: {
      edges
    }
  }
}) => {
  return (
    <>
      {edges.map(({ node }) => {
        const { frontmatter, html, excerpt } = node
        const { name, e_mail } = frontmatter
        const { fluid } = frontmatter.avatar.childImageSharp
        return (
          <div className="autoria flex flex-row w-full lg:flex-wrap">
            <div className="bg-white rounded rounded-full border border-criptoOrange-300 lg:border-none lg:mx-auto w-20 h-20 p-1 mr-3 lg:-mb-6 z-40 ">
            <Img
              fluid={fluid}
              alt={name}
              className="w-full h-full rounded rounded-full"
            />
            </div>
            <div className="pl-1 lg:px-2 lg:pt-6 w-3/4 lg:w-full z-10">
              <div className="font-display tracking-wider uppercase text-sm">Autor:</div>
              <div className="font-light tracking-wide mb-2 text-sm">
                  {name}                
              </div>
              <div className="font-display tracking-wider uppercase text-sm">Sobre o Autor:</div>
              <div className="font-light font-body tracking-wider text-left text-gray-700 text-sm">
                <div id="excerpt" className="mt-2 mb-3 font-light" dangerouslySetInnerHTML={{ __html: excerpt }} />
                <Link to="">Clique para saber mais</Link>
              </div>
              <div className="font-display tracking-wider uppercase text-sm">Entre em contato:</div>
              <div className="font-light tracking-wide mb-2 text-sm">
                <Link to={`mailto:${kebabCase(e_mail)}`}>{e_mail}</Link>
              </div>
            </div>
          </div>            
        )
      })}
    </>
  )
}


export default function Template({ data }) {
  const { markdownRemark, id } = data // data.markdownRemark holds your post data
  const { frontmatter, html } = markdownRemark

  return (

        <BlogLayout id={id} kind="artigo">
      <div className="container mx-auto lg:px-16">
        <div id="wrapper" className="w-full flex flex-wrap items-start">
        <div 
          className={`
          ( ... Tailwind CSS Classes ... )
          `} 
          postName={frontmatter.title}>
          <Img 
            fluid={frontmatter.featuredImage.childImageSharp.fluid}  
            className={`
            ( ... Tailwind CSS Classes ... )
            `}
            style={{maxHeight: 768, backgroundPosition: `center`}}
            />

          <h1 
            className={`
            ( ... Tailwind CSS Classes ... )
            `}>
            <TextScramble>
              {frontmatter.title}
            </TextScramble> 
          </h1>
        </div>          

        <div className="w-full md:w-3/4 mx-auto lg:mx-0 lg:w-1/6 mt-12 pt-6 border-t lg:border-none lg:-mt-10 z-30 order-3 lg:order-2" id="autoria">
          <Autoria data={data} />
        </div>

        <div className="content-body w-full lg:w-4/6 pt-3 lg:pt-10 px-4 md:px-24 font-body font-light order-2 lg:order-3"
                    dangerouslySetInnerHTML={{ __html: html }}
                />

        <div className="w-3/4 mx-auto lg:w-1/6 pt-3 order-last">
          <div className="complementos " id="meta">
            <div className="pl-24 lg:px-0 pt-12 w-full z-10">
              <div className="categorias">
                <div className="font-display tracking-wider uppercase text-sm">
                  Categorias:
                </div>

                <ul className=" mb-4">
                  {frontmatter.categories.map(( category , i ) => (
                    <li className={`
                    ( ... Tailwind CSS Classes ... )
                    `}>
                      <AniLink
                        paintDrip
                        duration={1}
                        key={i}
                        to={`/categorias/${kebabCase(category)}/`}>
                          {category}
                      </AniLink>
                    </li>
                  ))}
                </ul>
              </div>

              <div className="tags">
                <div className="font-display tracking-wider uppercase text-sm">
                  Tags:
                </div>

                <ul className="mb-4">
                  {frontmatter.tags.map(( tag , i ) => (
                    <li className={`
                    ( ... Tailwind CSS Classes ... )
                  `}>
                      <AniLink
                        paintDrip
                        duration={1}
                        key={i}
                        to={`/tags/${kebabCase(tag)}/`}>
                          {tag}
                      </AniLink>
                    </li>
                  ))}
                </ul>
              </div>

              </div>

            </div>
          </div>
        </div>

      </div>

    </BlogLayout>

  )
}

export const pageQuery = graphql`
  query(
    $slug: String!
    ) {
    markdownRemark(
      fields: { 
        slug: { 
          eq: $slug 
        } 
      }, 
      frontmatter: { 
        type: { 
          eq: "blog-post"
          } 
        } 
      ) {
      html
      id
      fields {
        slug
      }
      frontmatter {
        date(formatString: "DD MMMM YYYY")
        path
        title
        categories
        tags
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 1200) {
              ...GatsbyImageSharpFluid
            }
          }
        }                               
      }
    }
    allMarkdownRemark(
      filter: {
        frontmatter: {
          type: {
            eq: "autor" 
          },
        }
      }, 
      limit: 1
    ) {
    edges {
      node {
        html
        excerpt(format: PLAIN, pruneLength: 200)
        frontmatter {
          name
          avatar {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
          slug
          e_mail
        }
      }
    }
  }
  }
`

Я хочу работать так, чтобы получить такой запрос:

query(
    $slug: String!, 
    $autor: String!
    ) {
    markdownRemark(
      fields: { 
        slug: { 
          eq: $slug 
        } 
      }, 
      frontmatter: { 
        type: { 
          eq: "blog-post"
          } 
        } 
      ) {
      html
      id
      fields {
        slug
      }
      frontmatter {
        date(formatString: "DD MMMM YYYY")
        path
                title
                categories
                tags
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 1200) {
              ...GatsbyImageSharpFluid
            }
          }
        }                               
      }
    }
    allMarkdownRemark(
      filter: {
        frontmatter: {
          type: {
            eq: $autor <-------- New var 
          },
        }
      }, 
      limit: 1
    ) {
    edges {
      node {
        html
        excerpt(format: PLAIN, pruneLength: 200)
        frontmatter {
          name
          avatar {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
          slug
          e_mail
        }
      }
    }
  }
}

Является ли это возможным? Я пробовал это до сих пор безуспешно.


person Eduardo Oliveira    schedule 16.04.2020    source источник


Ответы (2)


Вы правильно передаете переменные через контекст, но вам нужно удалить восклицательный знак в переменной $author! (что означает, что не допускает значения NULL). Ваш код должен выглядеть так:

query($slug: String!, $autor: String) {
    markdownRemark(fields: { slug: { eq: $slug }}, 
      frontmatter: { 
        type: { 
          eq: "blog-post"
          } 
        } 
      ) {
      html
      id
      fields {
        slug
      }
      frontmatter {
        date(formatString: "DD MMMM YYYY")
        path
                title
                categories
                tags
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 1200) {
              ...GatsbyImageSharpFluid
            }
          }
        }                               
      }
    }
    allMarkdownRemark(
      filter: {
        frontmatter: {type: {eq: $autor}}}, 
      limit: 1
    ) {
    edges {
      node {
        html
        excerpt(format: PLAIN, pruneLength: 200)
        frontmatter {
          name
          avatar {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
          slug
          e_mail
        }
      }
    }
  }
}

Дополнительную информацию о схемах и типах GraphQL можно найти здесь.

person Ferran Buireu    schedule 16.04.2020
comment
Я не понял этого '!' смысл тогда. Спасибо за объяснение и ссылку! - person Eduardo Oliveira; 16.04.2020

В запросе отсутствует автор

    query($slug: String!, $autor: String) {
    markdownRemark(
      fields: { 
        slug: { 
          eq: $slug 
        } 
      }, 
      frontmatter: { 
        type: { 
          eq: "blog-post"
          } 
        } 
      ) {
      html
      id
      fields {
        slug
      }
      frontmatter {
        date(formatString: "DD MMMM YYYY")
        path
        title
        categories
        tags
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 1200) {
              ...GatsbyImageSharpFluid
            }
          }
        }                               
      }
    }
    allMarkdownRemark(
      filter: {
        frontmatter: {
          type: {
            eq: "autor" 
          },
        }
      }, 
      limit: 1
    ) {
    edges {
      node {
        html
        excerpt(format: PLAIN, pruneLength: 200)
        frontmatter {
          name
          avatar {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
          slug
          e_mail
        }
      }
    }
  }
person mkEagles    schedule 16.04.2020
comment
Он передается через контекст в autor: node.frontmatter.name. Он присваивает autor значение node.frontmatter.name, которое запрашивается - person Ferran Buireu; 16.04.2020
comment
Я видел. Я исправил свою часть запроса, он пропустил добавление автора в запрос. - person mkEagles; 16.04.2020
comment
Я сделал, mkEagles. Спасибо, что указали на это. allMarkdownRemark (filter: {f rontmatter: {type: {eq: $ autor},}}, limit: 1) {...} - person Eduardo Oliveira; 16.04.2020