如何使用图像组件将图像动态添加到Gatsby中的页面?

时间:2020-09-16 03:54:48

标签: reactjs gatsby gatsby-image

因此,我有一个可以渲染2张不同图像的图像组件,但是我希望能够将我的图像组件添加到任何页面,并仅将特定图像作为道具传递,而不必对新查询进行硬编码我需要使用的每个图像。

如果我有50张图像,我想仅将image-50.jpg作为道具传递,而不是对其进行特定查询。是否可以在gatsby中使用graphql做到这一点?

这是我当前的图像组件代码

      import { graphql, useStaticQuery } from "gatsby"
      import Img from "gatsby-image"
      import React from "react"

      const Image = () => {
        const data = useStaticQuery(graphql`
          query {
            astronaut: file(relativePath: { eq: "gatsby-astronaut.png" }) {
              childImageSharp {
                fluid(maxHeight: 600) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
            person: file(relativePath: { eq: "profile.jpg" }) {
              childImageSharp {
                fluid(maxHeight: 600) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        `)

        return (
          <>
            <Img fluid={data.astronaut.childImageSharp.fluid} />
            <Img fluid={data.person.childImageSharp.fluid} />
          </>
        )
      }

      export default Image

有没有一种方法可以动态添加图像,然后将其渲染到新页面?

类似 <Image src={"profile.jpg"} />

我不知道如何将其添加到graphql并想象我有50张图像,那么我将不得不映射全部50张图像或手动添加每个查询,这没有意义

2 个答案:

答案 0 :(得分:0)

信不信由你,你不能使用gastby-image创建一个完全动态的图像组件,而又不会冒捆绑包大小(可能很大)的风险。问题在于Gatsby中的静态查询在其模板文字中不支持字符串插值。每次使用该组件时,您都需要搜索所有文件。 您可以在here的现有SO帖子中尝试一些解决方案。

您始终可以使用graphql片段并为查询编写类似以下内容的内容,然后根据通过Image组件中的prop传递的文件名有条件地渲染正确的图像,但是可惜这也很笨拙:

export const fluidImage = graphql`
fragment fluidImage on File {
  childImageSharp {
    fluid(maxWidth: 1000) {
      ...GatsbyImageSharpFluid
    }
  }
}
`;

export const data = graphql`
  query {
    imageOne: file(relativePath: { eq: "one.jpg" }) {
      ...fluidImage
    }
    imageTwo: file(relativePath: { eq: "two.jpg" }) {
      ...fluidImage
    }
    imageThree: file(relativePath: { eq: "three.jpg" }) {
      ...fluidImage
    }
  }
`
// accessed like this
<Img fluid={data.imageOne.childImageSharp.fluid} />
// or this
<Img fluid={data.imageTwo.childImageSharp.fluid} />
// or this, dynamically (if you had a prop called imageName)
<Img fluid={data.[`${props.imageName}`].childImageSharp.fluid} />

答案 1 :(得分:0)

正如Apena's answer所解释的那样,要像Gatsby的Image那样工作是很棘手的。但是,我必须说,您可以根据所使用的文件系统以及数据的结构以不同的方式绕过它。

请记住,如果您在gatsby-config.js中正确设置了文件系统,则将允许Gatsby识别并找到项目中的所有图像,使其可查询,并允许Gatsby Image组件使用它们。

const path = require(`path`)

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: path.join(__dirname, `src`, `images`),
      },
    },
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
  ],
}

与查询按路径过滤的staticQuery中的每个图像相比,您可以找到更好的方法,这不是唯一的实现方法。当然,如果您使用的是staticQuery方法,则使其动态变化的局限性迫使您分别进行每个查询。

首先,您需要了解staticQuery and page query之间的区别,以了解适合您的地方以及它们的局限性。

如果使用页面查询,则始终可以创建类似于以下方法:

import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/layout'

class ProductPage extends React.Component {
  render() {

    const products = get(this, 'props.data.allDataJson.edges')

    return (
      <Layout>
        {products.map(({ node }) => {
          return (
            <div key={node.name}>
              <p>{node.name}</p>
              <Img fluid={node.image.childImageSharp.fluid} />
            </div>
          )
        })}
      </Layout>
    )
  }
}

export default ProductPage


export const productsQuery = graphql`
  query {
    allDataJson {
      edges {
        node {
          slug
          name
          image{
            publicURL
            childImageSharp{
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  }
`

在上面的示例中,您正在使用页面查询来从JSON文件检索所有图像。如果在文件系统中设置路径,则可以使用GraphQL片段检索它们。在处理Gatsby Image时,这种方法更具动态性,最好一一查询。

对于其他文件系统,此想法仍然相同,这只是一种可适应的方法。如果您使用诸如Contentful之类的CMS,则可以下载资产并以相同的方式动态查询资产,因为文件系统允许您这样做。

页面查询仅在页面组件中被允许(因此命名),因此,如果您想在React独立组件中使用它以使其可重用,则需要通过props(或reducer)传递给所需的组件,并且根据收到的道具渲染盖茨比图像。