Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discussion] Allow substitution in graphql string templates #3186

Closed
sarahatwork opened this issue Dec 11, 2017 · 8 comments
Closed

[Discussion] Allow substitution in graphql string templates #3186

sarahatwork opened this issue Dec 11, 2017 · 8 comments

Comments

@sarahatwork
Copy link
Contributor

@sarahatwork sarahatwork commented Dec 11, 2017

I'm new to graphql, but I find a lot of my queries are very long and repetitive, and being able to interpolate repeated sections would make my code a lot easier to read and update.

Here's one section of graphql I have on one of my templates:

      # SUBNAV PROPERTIES - CATEGORY
      overviewNavTitle
      categorySlug: slug
      subcategories {
        description: navDescription
        id
        slug
        title: navTitle
      }

      # SUBNAV PROPERTIES - NESTED ARTICLE
      parentCategory: contentpage {
        categoryTitle: navTitle
        categoryDescription: navDescription
        overviewNavTitle
        categorySlug: slug
        subcategories {
          description: navDescription
          id
          slug
          title: navTitle
        }
      }

I wish I could write it like this:

      # SUBNAV PROPERTIES - CATEGORY
      ${commonNavProps}

      # SUBNAV PROPERTIES - NESTED ARTICLE
      parentCategory: contentpage {
        categoryTitle: navTitle
        categoryDescription: navDescription
        ${commonNavProps}
      }

But I get an error triggered by this code: https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/babel-plugin-extract-graphql.js#L10

This code does not run on queries in my gatsby-node file, so I've been taking advantage of interpolation there and it's made things a lot easier.

I tried to look into a solution for this myself, but I'm a bit out of my element dealing with babel ASTs, so I thought I'd pause and see:

  • Is this something other people are interested in? (Maybe even people who know how to fix the issue?)
  • Is there a way to get around the problem? My best idea so far is to do more of my queries in gatsby-node and send the results to my templates using templateContext, but that feels wrong 😕
@calcsam

This comment has been minimized.

Copy link
Member

@calcsam calcsam commented Dec 12, 2017

It sounds like you're looking for the GraphQL concept of fragments: http://graphql.org/learn/queries/#fragments. Gatsby doesn't support variable names in GraphQL queries as explained here: #2293

@sarahatwork

This comment has been minimized.

Copy link
Contributor Author

@sarahatwork sarahatwork commented Dec 12, 2017

Thanks @calcsam. I had tried those before (and I'm using inline fragments elsewhere) but I guess I had the formatting wrong because I couldn't get them to work. Your comment inspired me to try them again and now I have it working. Fragments are more flexible than I thought. I guess that solves the issue!

@aderaaij

This comment has been minimized.

Copy link
Contributor

@aderaaij aderaaij commented Dec 12, 2017

@sarahatwork how did you get them to work? Do you add them to an external graphql file and import them or so? Any hints would be appreciated ;)

@KyleAMathews

This comment has been minimized.

Copy link
Contributor

@KyleAMathews KyleAMathews commented Dec 12, 2017

Put them wherever it makes sense e.g. in the same page or in a component. Fragments are in a global namespace so you don't have to import them explicitly.

@KyleAMathews

This comment has been minimized.

Copy link
Contributor

@KyleAMathews KyleAMathews commented Dec 12, 2017

They do need to be in a js file though. We don't support .graphql files atm.

@sarahatwork

This comment has been minimized.

Copy link
Contributor Author

@sarahatwork sarahatwork commented Dec 12, 2017

Yeah in my case it wound up being:

export const pageQuery = graphql`
  fragment commonNavProps on ContentfulContentPage {
    overviewNavTitle
    categorySlug: slug
    subcategories {
      description: navDescription
      id
      slug
      title: navTitle
    }
  }

  query contentPageQuery($id: String!) {
    contentfulContentPage(id: { eq: $id }) {
      # SUBNAV PROPERTIES - CATEGORY
      ...commonNavProps

      # SUBNAV PROPERTIES - NESTED ARTICLE
      parentCategory: contentpage {
        categoryTitle: navTitle
        categoryDescription: navDescription
        ...commonNavProps
      }
  }
`;

Still can't do everything I want, like a fragment containing inline fragments, but still reducing some repetition.

@aderaaij

This comment has been minimized.

Copy link
Contributor

@aderaaij aderaaij commented Dec 12, 2017

Ah thank you both! I was confused by the syntax, I tried to declare them without template strings so no wonder it didn't work. Graphql was already nice but this is wonderful!

@dandv

This comment has been minimized.

Copy link
Contributor

@dandv dandv commented Nov 11, 2019

I'm looking for a more general use case: interpolating the same query in different places. For example, the Sourcing from Ghost example could be fleshed out to output a list of posts with the title linking to the slug. That needs a page with another allGhostPost GraphQL query for the set of posts, repeating the query from gatsby-node.js and only adding the title field.

If interpolation in the graphql tag worked, one could write a single query for both, returning the slug and title. In gatsby-node.js, the title would be ignored, but it would be used when creating the lists of posts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.