简体   繁体   English

组件中的React / Gatsby动态背景图像

[英]React / Gatsby dynamic background images in a component

I've got a React component that essentially does related content, showing a user the next / prev pieces of content inside of a site. 我有一个React组件,它基本上可以处理相关内容,向用户显示网站内的下一个/上一页内容。

This component needs to import background images so I can use them as inline styles inside of the component. 此组件需要导入背景图像,以便我可以将它们用作组件内部的内联样式。 However, to know which background image I want to import, I have to look at the props which get defined like this: 但是,要知道我要导入哪个背景图像,我必须查看定义如下的道具:

<LocationRelated 
  previousLocationName="Columbus, OH"
  previousLocationPath="columbus"
  nextLocationName="St. Pete Beach, FL"
  nextLocationPath="st-pete-beach"
/>

But, as far as I can tell, there isn't a way to look at the props of a component before it enters React's render function - thus no way to do a dynamic import. 但是,据我所知,在进入React的render函数之前,没有办法查看组件的道具 - 因此无法进行动态导入。

This is my broken attempt at doing this, using an ES6 template literal inside of the import: 这是我在执行此操作时的破坏尝试,使用导入内部的ES6模板文字:

import React from "react"
import pfbRelatedPrevBGImagePath from '`../../images/grid/PFB_${this.props.previousLocationPath}.jpg`'
import pfbRelatedNextBGImagePath from '`../../images/grid/PFB_${this.props.nextLocationPath}.jpg`'

class LocationRelated extends React.Component {

  render() {

    const pfbRelatedPrevBG = { 
      backgroundImage: `linear-gradient( to bottom, rgba(1,1,1,0.2), rgba(2,2,2,0.2) ), url(${ pfbRelatedPrevBGImagePath })` 
    }
    const pfbRelatedNextBG = { 
      backgroundImage: `linear-gradient( to bottom, rgba(1,1,1,0.2), rgba(2,2,2,0.2) ), url(${ pfbRelatedNextBGImagePath })` 
    }

    return (
      <div>
        <aside className="pfb-longform-container">
          <section className="pfb-related-content">
            <h3 className="pfb-related-content-title">Additional Locations</h3>
            <section className="pfb-related-image-container">
              <div 
                className="pfb-related-1" 
                style= { pfbRelatedPrevBG }
              >
                <p className="pfb-related-text">{ this.props.previousLocationName }</p>
              </div>
              <div 
                className="pfb-related-2"
                style= { pfbRelatedNextBG }
              >
                <p className="pfb-related-text">{ this.props.nextLocationName }</p>
              </div>
            </section>
          </section>
        </aside>
      </div>
    )
  }
}

export default LocationRelated

My webpack builder errors out, saying basically it can't read this.props.whatever because it hasn't been defined yet when it tries to read the import . 我的webpack构建器出错了,说基本上它无法读取this.props.whatever因为它在尝试读取import this.props.whatever未定义。 Is there a way to do this? 有没有办法做到这一点?

Additional note: I'm using the Gatsby static site generator for this site, but that shouldn't really impact what's happening (at least I don't think it should). 附加说明:我正在为此站点使用Gatsby静态站点生成器,但这不应该真正影响正在发生的事情(至少我认为不应该)。

The above approach is impossible as best I can tell, but as I discovered, it's impossible for a good reason. 我认为上述方法是不可能的,但正如我发现的那样,这是不可能的。 You have to FULLY give into the React (Gatsby) way of doing things and my approach above was trying to do this from a Drupal/WordPress-CMS-build perspective. 你必须完全放弃React(Gatsby)的做事方式 ,我上面的方法试图从Drupal / WordPress-CMS-build的角度来做这件事。

Check out my revised component for LocationRelated : 查看我修订的LocationRelated组件:

import React from "react"
import Link from 'gatsby-link'

class LocationRelated extends React.Component {

  render() {

    // Setup inline style objects using ES6 template literals which pull in the correct paths from the content pages themselves
    const pfbRelatedPrevBG = { 
      backgroundImage: `linear-gradient( to bottom, rgba(1,1,1,0.2), rgba(2,2,2,0.2) ), url(${ this.props.prevLocationImgPath.sizes.src })` 
    }
    const pfbRelatedNextBG = { 
      backgroundImage: `linear-gradient( to bottom, rgba(1,1,1,0.2), rgba(2,2,2,0.2) ), url(${ this.props.nextLocationImgPath.sizes.src })` 
    }

    return (
      <div className="pfb-related-bg-container">
        <aside className="pfb-related-container">
          <section className="pfb-related-content">
            <section className="pfb-related-image-container">
              <Link 
                to={ this.props.prevLocationPath }
                className="pfb-related-left-arrow"
              >
                <img src= { LeftArrow } alt="Navigate to the previous location in the PFB Annual Report" />
                <div className="pfb-related-left-arrow-text">Previous</div>
              </Link>
              <Link 
                to={ this.props.prevLocationPath }
                className="pfb-related-1" 
                style={ pfbRelatedPrevBG }
              >
                <p className="pfb-related-text">{ this.props.prevLocationName }</p>
              </Link>
              <Link 
                to={ this.props.nextLocationPath }
                className="pfb-related-2"
                style= { pfbRelatedNextBG }
              >
                <p className="pfb-related-text">{ this.props.nextLocationName }</p>
              </Link>
              <Link 
                to={ this.props.nextLocationPath }
                className="pfb-related-right-arrow"
              >
                <img src= { RightArrow } alt="Navigate to the next location in the PFB Annual Report" />
                <div className="pfb-related-right-arrow-text">Next</div>
              </Link>
            </section>
          </section>
        </aside>
      </div>
    )
  }
}

export default LocationRelated

You'll notice not much is different than the above attempt but pay attention to the this.props.nextLocationImgPath.sizes.src path being used in the backgroundImage object literal. 您会注意到与上述尝试没有太大区别,但要注意backgroundImage对象文字中使用的this.props.nextLocationImgPath.sizes.src路径。 You have to pass backgroundImage the source path as a prop. 您必须将backgroundImage作为道具传递给源路径。 Don't try to do it in the component like I was. 不要试图像我一样在组件中这样做。 React's separation of concerns is about getting data out of components and instead feeding data in through props. React关注点的分离是关于从组件中获取数据,而是通过props提供数据。

So then the question becomes: if you have to pass the path in as a prop, how do you get the path when you call your component at the page level? 那么问题就变成了:如果你必须将路径作为道具传递,那么当你在页面级别调用组件时,如何获得路径?

If you're using Gatsby (and you should), you need to use GraphQL to get the optimized image paths. 如果你正在使用Gatsby (你应该),你需要使用GraphQL来获得优化的图像路径。 In my example, we will call for background-image path on the same page where we would call the LocationRelated component. 在我的示例中,我们将在我们调用LocationRelated组件的同一页面上调用background-image路径。

Simplified example of my page that concentrates on the issue at hand: 我的页面的简化示例专注于手头的问题:

import React from 'react'
import Img from "gatsby-image";

import LocationRelated from '../components/LocationRelated'

class CharlotteLocation extends React.Component {
  render() {
    return (
      <div>    
        <LocationRelated 
          prevLocationName="Detroit"
          prevLocationPath="detroit"
          prevLocationImgPath= { this.props.data.charlottePrevImage }
          nextLocationName="Montana"
          nextLocationPath="montana"
          nextLocationImgPath= { this.props.data.charlotteNextImage }
        />
      </div>
    )
  }
}

export default CharlotteLocation 

// GraphQL queries for each image
export const CharlotteImageQuery = graphql`
  query CharlotteImageQuery {
    charlottePrevImage: imageSharp(id: { regex: "/PFB_DETROIT/" }) {
      sizes(maxWidth: 600 ) {
        ...GatsbyImageSharpSizes_withWebp
      }
    },
    charlotteNextImage: imageSharp(id: { regex: "/PFB_MONTANA/" }) {
      sizes(maxWidth: 600 ) {
        ...GatsbyImageSharpSizes_withWebp
      }
    }
  }
`

These GraphQL queries make available the optimized paths to the files we need, and now we can send them into our LocationRelated component via this.props.data . 这些GraphQL查询提供了我们所需文件的优化路径,现在我们可以通过this.props.data将它们发送到我们的LocationRelated组件。

gatsby-image and GraphQL are a bit tricky to work with at first so check out this nice tutorial by Kyle Gill . gatsby-image和GraphQL起初使用起来有点棘手,所以请查看Kyle Gill的这个精彩教程 It got me going a bit better than the Gatsby documentation did. 它让我比Gatsby文档做得更好。

For reference, here is how I set up my gatsby-config.js in the project to get all these plugins working nicely together (I'm pulling the images from a standalone images directory in my project rather than in a component, so I needed gatsby-source-filesystem to make all this work along with gatsby-image , gatsby-transformer-sharp , gatsby-plugin-sharp ,): 作为参考,这里是我如何在项目中设置我的gatsby-config.js以使所有这些插件很好地协同工作(我从我项目中的独立images目录而不是组件中提取图像,所以我需要gatsby-source-filesystem使这一切与gatsby-image一起工作, gatsby-transformer-sharpgatsby-plugin-sharp ,):

module.exports = {
  siteMetadata: {
    title: 'PFB2017 Site',
  },
  //pathPrefix: "/pfb2017-site",
  plugins: [
    // Adds in React Helmet for metadata
    `gatsby-plugin-react-helmet`,

    // Gives us sass in the project
    `gatsby-plugin-sass`,

    // This plugin transforms JSON, which is how we are storing our location data
    `gatsby-transformer-json`,

    // Adds in Gatsby image handling
    `gatsby-image`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,

    /** 
     * This is how you customize gatsby-source-filesystem
     * Check this page out for more background 
     * https://www.gatsbyjs.org/docs/building-with-components 
     * By default, the gatsby-default starter kit comes with the `pages` directory wired up
     * I'm adding it here for consistency but you don't need it
     * What I have added into the starter are `images` and `data`, subfolders we'll need for the PFB project
     * 
     */

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`,
        path: `${__dirname}/src/pages`,
      },
    },    
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/src/data`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`
      }
    }
  ],
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM