String interpolation in graphQL query
Asked Answered
O

4

11

I am new to Gatsby and its graphQL query system to retrieve assets. I have a working component Image that fetches an image and displays it. I want to have the name of the image customizable but I can't figure out how to dit.

Here is the working component:

const Image = () => (
  <StaticQuery
    query={graphql`
      query {
        // fetching the image gatsby-astronaut.png
        placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
  />
);

And here is what I tried to have a customizable image:

const Image = ({ imgName }: { imgName: string }) => (
  <StaticQuery
    query={graphql`
      query {
        // fetching the image imgName
        placeholderImage: file(relativePath: { eq: "${imgName}.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
  />
);

But it raises the following error for the query:

Expected 1 arguments, but got 2.ts(2554)

How can I have a customizable image name?

Occiput answered 13/5, 2019 at 19:5 Comment(0)
E
4

Here is the easy way I ran into:

const Image = props => {
  const data = useStaticQuery(graphql`
    query {
      firstImg: file(relativePath: { eq: "firstImg.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }

      secondImg: file(
        relativePath: { eq: "secondImg.png" }
      ) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  switch (props.name) {
    case "firstImg":
      return <Img fluid={data.firstImg.childImageSharp.fluid} />
    case "secondImg":
      return <Img fluid={data.secondImg.childImageSharp.fluid} />
    default:
      return <Img />
  }
}

and use it like this:

<Image name="firstImg" />

You can also make it typo-safe by introducing an object with all the images you might want to display, like this:

const Images = { firstImg: 'firstImg', secondImg: 'secondImg' }

and then use it like this:

<Image name={Images.firstImage} />

and

...
switch (props.name) {
case Images.firstImage:
...
Elisabethelisabethville answered 22/8, 2020 at 19:32 Comment(1)
Very convenientOcciput
D
3

Check the docs for static query

StaticQuery can do most of the things that page query can, including fragments. The main differences are:

  • page queries can accept variables (via pageContext) but can only be added to page components
  • StaticQuery does not accept variables (hence the name “static”), but can be used in any component, including pages

So you might want to query for the image's GatsbyImageSharpFluid in your page query and pass it as the fluid prop directly to gatsby image.

Deoxyribose answered 13/5, 2019 at 20:23 Comment(1)
I didn't manage to make it work but your answer is relevant. Thanks!Occiput
G
1

Using ksav answer I managed to make this work by using pageQuery and receive the images i want to use in a specific page through props.

Like this:

export const pageQuery = graphql`
  coverImage: file(relativePath: { eq: "coverImage.png" }) {
    childImageSharp {
      fluid(maxWidth: 600) {
        ...GatsbyImageSharpFluid_tracedSVG
      }
    }
  }
}`

If you add this to your page component you will receive the props coverImage with the coverImage.png image. Hope this helps!

Goldfinch answered 4/9, 2019 at 11:47 Comment(0)
S
0

This is one area where Gatsby could do better imho. I appreciate @ramzesenok's answer and if you must use the Gatsby framework with graphql that's probably the best you're going to do. But you could also just fall back to normal React like this:

import React from 'react';
import gatsbyAstronaut from './gatsby-astronaut.png'; 

and use it like this.

<img src={gatsbyAstronaut} alt="Gatsby Astronaut" />

Even this seems a little heavy but the import is required so webpack can bundle the image properly.

Sigismundo answered 23/9, 2022 at 12:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.