ianckc
ianckc

Reputation: 1716

GatsbyJS passing user input to GraphQL

I’m looking for examples / tutorials on accepting user input from a form in GatsbyJS and passing that to my GraphQL query.

I can get the user input on submit and also pass variables in when testing graphiql, I just can’t figure out how to combine the two.

My data is stored in Drupal and is a list of recipes.

I’d like the user to be able to type in an ingredient e.g. chicken and then retrieve all of the recipes where chicken is an ingredient.

My query is

query SearchPageQuery($ingredient: String) {
  allNodeRecipes(filter: {relationships: {field_ingredients: {elemMatch: {title: {eq: $ingredient}}}}}) {
    edges {
      node {
        id
        title
        path {
          alias
        }
        relationships {
          field_ingredients {
            title
          }
        }
      }
    }
  }
}

Upvotes: 0

Views: 595

Answers (1)

kennethormandy
kennethormandy

Reputation: 2150

If I’m understanding your question correctly, the short answer is you can’t, but another approach might work for you.

Gatsby’s GraphQL queries are run in advance as part of the static build of the site, so the data is part of the client-side JavaScript, but the queries have already been run by that point.

This is the same reason you can’t use JavaScript template literals in a StaticQuery:

// This doesn’t work
let myDynamicSlug = 'home'

return (
  <StaticQuery
    query={graphql`
query ExampleQuery {
  examplePage(slug: { eq: ${myDynamicSlug} }) {
    title
  }
}
`}
    render={data => {
      console.log(data)
    }}
  />
)

You’ll get an error message explaining “String interpolations are not allowed in graphql fragments.” Further reading: https://github.com/gatsbyjs/gatsby/issues/2293

I had a similar problem recently, and I realised it made a lot of sense why you can’t do this. If you are, ex. generating images using the queries in your GraphQL and things akin to that, you can’t pass in client side variables, because all the “static site” Gatsby operations like handling the images have are already done by that time.

What worked for me was to get the larger portion of data I needed in my query, and find what I needed within. In my previous example, that might mean getting allExamplePages instead of one examplePage, and then finding the myDynamicSlug I needed within it:

// This isn’t exactly how you’d hope to be able to do it,
// but it does work for certain problems
let myDynamicSlug = 'home'

return (
  <StaticQuery
    query={graphql`
query ExampleQuery {
  # You might still be able to limit this query, ex. if you know your item
  # is within the last 10 items or you don’t need any items before a certain date,
  # but if not you might need to query everything
  allExamplePages() {
    edges {
      node {
        title
        slug
      }
    }
  }
}
`}
    render={data => {
      // Find and use the item you want, however is appropriate here
      data.edges.forEach(item => {
        if (item.node.slug === myDynamicSlug) {
          console.log(item)
        }
      })
    }}
  />
)

In your case, that hopefully there is an equivalent, ex. looking something up based on the user input. If you can be more specific about the structure of your data, I’d be happy to try and make my suggestion more specific. Hope that helps!

Upvotes: 2

Related Questions