Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Complex query variables in GraphQL (via Gatsby)

Tags:

graphql

gatsby

I am building a localized static website using Gatsby, with the help of gatsby-plugin-intl. This plugin adds a context variable named intl to pages (including template-based pages), which is an object: https://github.com/wiziple/gatsby-plugin-intl/blob/master/src/gatsby-node.js#L27-L34

I would like to access the intl.language variable from the context within a page query. This is my (failing) code at this stage:

query($slug: String!, $intl: String) {
  contentfulPerson(slug: {eq: $slug}, node_locale: {eq: $intl.language}) {
    name
  }
}

Contentful is the headless CMS I use and from which I would like to fetch data in the correct locale.

Obviously this code has two problems: $intl is not a string, and $intl.language is not syntactically correct. But I don't know how to fix either problem.

I guess I could either fork the plugin or do something in my own gatsby-node.js to make the language available as a top-level variable in the context, but I'm interested to know if there is a way to do it directly. The Gatsby docs say that query variables can be complex (https://www.gatsbyjs.org/docs/graphql-reference/#query-variables) but in the example they provide, they don't show how the types are defined or how to access a property within these variables.


EDIT : I tried moving the language to a top-level context variable in my gatsby-node.js using this code:

exports.onCreatePage = ({page, actions}) => {
  const { createPage, deletePage } = actions
  deletePage(page)
  createPage({
    ...page,
    context: {
      ...page.context,
      language: page.context.intl.language
    }
  })
}

but the program runs out of memory (even when increasing max_old_space_size)

like image 822
Arnaud Avatar asked May 28 '19 11:05

Arnaud


1 Answers

You can move the language field to a top-level context by doing this:

exports.onCreatePage = ({ page, actions }) => {
  const { createPage, deletePage } = actions
  const oldPage = Object.assign({}, page)

  page.context.language = page.context.intl.language;
  if (page.context.language !== oldPage.context.language) {
    // Replace new page with old page
    deletePage(oldPage)
    createPage(page)
  }
}

Checking if the field has changed avoids the infinity loop.

like image 109
ConradoQG Avatar answered Oct 03 '22 08:10

ConradoQG