Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a value to a StaticQuery using props string?

I'm developing a site in Gatsby.js with a blog within and for a post layout, I'm coding this header with a background image to be set by the post author. I'm still in the designing phase, placing elements, blank texts etc.

I've made this component with BackgroundImage, graphQL and StaticQuery and within it's code, if I narrow the search for an image sourced from gatsby-source-filesystem with a "post_8.jpg" text, it works fine as it should.

import React from 'react'
import { graphql, StaticQuery } from 'gatsby'
import BackgroundImage from 'gatsby-background-image'
import TextScramble from './TextScramble'


const BackgroundDiv = ({ className, children }) => (
  <StaticQuery 
    query={graphql`
      query($post: String! ) {
        file(relativePath: {eq: "post_8.jpg"}) {
          childImageSharp {
            fluid {
              ...GatsbyImageSharpFluid
            }
          }
        }
        }
      `
    }
    render={data => {
      const imageData = data.file.childImageSharp.fluid
      return (
        <BackgroundImage
          Tag="div"
          className={className}
          fluid={imageData}
        >
    <h1 className="bg-white shaddow shadow-md py-1 px-4 w-auto inline-block text-4xl absolute bottom-0 mb-24"><TextScramble>{ children }</TextScramble></h1>
        </BackgroundImage>
      )}
    }
  />
)

export default BackgroundDiv

However, I'm wondering how I would pass the value from the frontmatter from the page that contains the post, to this component.

I've been thinking on using a value passed to the component, such as a postName. E.g:

const BackgroundDiv = ({ className, children, postName }) => (

Then, it would grab this value within the query in a string.

query={graphql`
      query($post: String! ) {
        file(relativePath: {eq: ${postName}}) {
          childImageSharp {
            fluid {
              ...GatsbyImageSharpFluid
            }
          }
        }
        }
      `
    }

I've made this simple addition above that didn't work. It fails on compile telling me

String interpolation is not allowed in graphql tag:

    9 |     query={graphql`   
   10 |       query($postName: String! ) {
 > 11 |         file(relativePath: {eq: ${postName}}) {
      |                                ^^^^^^^^^^^   
   12 |           childImageSharp {   
   13 |             fluid {   
   14 |               ...GatsbyImageSharpFluid

 File: [$pathToFolder]/gatsby-theme-cripto/src/components/backgroundDiv.js

I've seached for String interpolation problems on google and even ended here, but I couldn't relate those contents with my problem. I'm not a experienced dev so I believe I'm missing something. Any thoughts on this matter would be really appreciated, the same way any requests on codes I could post to help understanding this problem.

Thank you in advance!

like image 761
EdBucker Avatar asked Oct 16 '22 06:10

EdBucker


1 Answers

Short answer: You can't.

Follow the discussion on the github repo. If you scroll all the way down, it looks like it will be available in the next few releases.

Workaround

  • Query for all the data.
  • Filter for the specific data you need. You can use variables in array functions.

Here an implementation with gatsby-image that I use in my project

const Page = (props) => {
  const { data: { allFile: { edges } } } = props;
  const oneImage = edges.filter(edge => // filter with your variable
    edge.node.childImageSharp.fluid.originalName === props.yourVARIABLE)[0].node.childImageSharp.fluid;
  {/* ... */}
}
export const query = graphql`
// ...

EDIT

In your comment, you made a mistake destructuring your props in the parameters of your arrow function. This is your revised code:


const BackgroundDiv = (props) => { 
  // destructuring all the props to make it clear
  const postName = props.postName // the variable you want to filter for
  const className = props.className;
  const children = props.children;
  const { data: { allFile: { edges } } } = props; 

  const oneImage = edges.filter(edge =>  
    edge.node.childImageSharp.fluid.originalName === postName)[0].node.childImageSharp.fluid;
like image 177
EliteRaceElephant Avatar answered Oct 26 '22 23:10

EliteRaceElephant