【问题标题】:Gatsby conditional className based on frontmatterGatsby 基于 frontmatter 的条件类名
【发布时间】:2020-05-19 00:24:36
【问题描述】:

我正在尝试根据页面frontmatter 中定义的页面模板将split 的className 添加到我的标题中。我有一个名为split 的页面模板,并希望标题在使用该模板的页面上具有该类。这是我的模板:

layout.js

import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import { StaticQuery, graphql } from 'gatsby'

import Header from './header'
import Footer from './footer'
import '../css/main.scss'

import favicon from './favicon.png'

const Layout = ({ children, frontmatter }) => (
  <StaticQuery
    query={graphql`
      query PageInfoQuery {
        site {
          siteMetadata {
            title
            footer
          }
        }
        markdownRemark {
          frontmatter {
            template
          }
        }
      }
    `}
    render={data => (
      <>
        <Helmet
          title={data.site.siteMetadata.title}
          meta={[
            { name: 'description', content: 'Sample' },
            { name: 'keywords', content: 'sample, something' },
          ]}
          link={[
            {
              rel: 'shortcut icon',
              type: 'image/png',
              href: `${favicon}`,
            },
          ]}
        >
          <html lang="en" />
        </Helmet>
        <Header siteTitle={data.site.siteMetadata.title} frontmatter={data.markdownRemark.frontmatter}/>
        {children}
        <Footer footer={data.site.siteMetadata.footer} />
      </>
    )}
  />
)

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

header.js

import PropTypes from 'prop-types'
import React from 'react'

import Navbar from './navbar' 

const Header = ({ siteTitle, frontmatter }) => (
  <header className={ frontmatter.template === 'split' ? 'header split' : 'header' }>
    <section className="navigation">
      <Navbar siteTitle={siteTitle} />
    </section>
  </header>

)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: '',
}

export default Header

我知道data.markdownRemark.frontmatter 工作正常,就像在我的模板split.js 中一样,我可以使用{post.frontmatter.template}hero 元素中动态显示模板名称。为了全面起见,我也将其包括在内。

split.js

import React from 'react'
import Helmet from 'react-helmet'
// eslint-disable-next-line
import { Link, graphql } from 'gatsby'

import Layout from '../components/layout'

// import blocks
import Feature from '../components/blocks/feature'
import Hero from '../components/blocks/hero'

class BlocksTemplate extends React.Component {
  render() {
    const post = this.props.data.markdownRemark
    const siteTitle = this.props.data.site.siteMetadata.title
    const siteDescription = post.excerpt
    const heroImage = post.frontmatter.hero_image.childImageSharp.fixed.src

    return (
      <Layout location={this.props.location} title={siteTitle}>
        <Helmet
          htmlAttribute={{ lang: 'en' }}
          meta={[{ name: 'description', content: siteDescription }]}
          title={`${post.frontmatter.title} • ${siteTitle}`}
        />
        <section className="hero" style={{ backgroundImage: `url(${heroImage})` }}>
          <h4 className="name">
            <Link to="/">
              {this.props.siteTitle}
              {post.frontmatter.template}
            </Link>
          </h4>
        </section>
        {post.frontmatter.blocks.map(block => {
          switch (block.component) {
            case 'feature':
              return <Feature block={block} />
            case 'hero':
              return <Hero block={block} />
            default:
              return ''
          }
        })}
      </Layout>
    )
  }
}

export default BlocksTemplate

export const pageQuery = graphql`
  query SplitPageBySlug($slug: String!) {
    site {
      siteMetadata {
        title
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      excerpt
      html
      frontmatter {
        template
        title
        hero_image {
          childImageSharp {
            fixed(width: 1500) {
              src
            }
          }
        }
        blocks {
          component
          image {
            childImageSharp {
              fixed(width: 1500) {
                src
              }
            }
          }
        }
      }
    }
  }
`

这是正在呈现的标题标记;本质上,split 类永远不会被添加。

<header class="header">
  <section class="navigation">
    <nav class="nav" role="navigation">
      <div class="branding">
        <a href="/"><h6 class="name">Jesse Winton</h6></a>
      </div>
      <a href="/">Home</a>
      <a aria-current="page" class="" href="/about-the-demo">What is this?</a>
      <a href="/about-the-ssg">About Gatsby</a>
      <a href="/posts">Blog</a>
    </nav>
  </section>
</header>

我对 Gatsby 还很陌生,因此非常感谢任何帮助!谢谢!

【问题讨论】:

  • 你能解释一下是什么问题吗?
  • @coreyward 更新了我的问题以提供更清晰的信息。谢谢!
  • 这仅仅是frontmatter.templateHeader 中永远不会成为"split" 的问题吗?
  • 是的,它实际上并没有在使用拆分模板的页面上显示 className。
  • 我在hero 中看不到{post.frontmatter.template} ... ` {this.props.siteTitle} {post.frontmatter.template} ` - 只有siteTitle 渲染?

标签: html reactjs jsx gatsby


【解决方案1】:

layout.js 中,您将frontmatter={data.markdownRemark.frontmatter} 传递给layout.js 中上面查询的标题。这是一个staticQuery,它将始终返回相同的数据。

我看到您正在 split.js 中的 pageQuery 中查询正确的数据,但这些数据并未传递给 split.js 中的布局:

<Layout location={this.props.location} title={siteTitle}>

解决此问题的一种方法是将模板名称传递给布局道具,就像您已经在使用位置和标题属性一样。

另一种方法是使用gatsby-plugin-layout 插件,它为布局组件返回 V1 Gatsby 的旧行为,为每个组件添加一个布局包装器。然后你可以直接将pageContext 分配给拆分组件。

【讨论】:

  • 谢谢你!你能帮我澄清一下如何将数据传递到标题并基于模板添加类吗?就像我说的,我对 Gatsby 和 React 还很陌生,所以任何帮助都会很棒!
猜你喜欢
  • 1970-01-01
  • 2023-01-21
  • 2022-01-25
  • 2020-02-24
  • 2019-12-29
  • 2019-01-23
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
相关资源
最近更新 更多