首页 > 解决方案 > GatsbyJS 将用户输入传递给 GraphQL

问题描述

我正在寻找有关从 GatsbyJS 中的表单接受用户输入并将其传递给我的 GraphQL 查询的示例/教程。

我可以在提交时获取用户输入,也可以在测试 graphiql 时传递变量,我只是不知道如何将两者结合起来。

我的数据存储在 Drupal 中,是一个食谱列表。

我希望用户能够输入一种成分,例如鸡肉,然后检索所有以鸡肉为成分的食谱。

我的查询是

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

标签: graphqlgatsby

解决方案


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!


推荐阅读