Search code examples
javascripttypescriptgraphqlgatsby

String interpolation in graphQL query


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?


Solution

  • 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:
    ...