Gatsby: [v2] Using a variable for the `query` prop of the `StaticQuery` component won't work

Created on 18 Jul 2018  Â·  5Comments  Â·  Source: gatsbyjs/gatsby

Description

If I try to assign my GraphQL to a variable as a const, and then pass it to my query prop of my <SaticQuery/> component, I only get __"Loading (StaticQuery)"__ rendered on my page.

Steps to reproduce

In your functional layout component assign, inside your <SaticQuery/>, your GraphQL query to a const like:

const Layout = ({ children }) => {
    const layoutQuery = graphql`
        query SiteTitleQuery {
            site {
                siteMetadata {
                    title
                }
            }
        }
    `
    return (
    <StaticQuery
        query={layoutQuery}
        … // something else
    />
    )
}

Expected result

I expected to get the const variable parsed as a normal GraphQL query getting, then, a rendered page.

Actual result

I only got a white page with the words __"Loading (StaticQuery)"__ on it (no errors in console).

Environment

System:
OS: macOS High Sierra 10.13.6
CPU: x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
Shell: 5.3 - /bin/zsh
Binaries:
Node: 8.11.3 - ~/.nvm/versions/node/v8.11.3/bin/node
npm: 6.1.0 - ~/.nvm/versions/node/v8.11.3/bin/npm
Browsers:
Chrome: 67.0.3396.99
Safari: 11.1.2
npmPackages:
gatsby: next => 2.0.0-beta.46
gatsby-image: next => 2.0.0-beta.6
gatsby-plugin-react-helmet: next => 3.0.0-beta.3
gatsby-plugin-sass: next => 2.0.0-beta.5
gatsby-plugin-sharp: next => 2.0.0-beta.5
gatsby-source-filesystem: next => 2.0.1-beta.6
gatsby-transformer-remark: next => 2.1.1-beta.3
npmGlobalPackages:
gatsby: 2.0.0-beta.46

File contents (if changed)

gatsby-config.js:

module.exports = {
    siteMetadata: {
        title: 'Gatsby Default Starter',
    },
    plugins: [
        `gatsby-plugin-react-helmet`,
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                path: `${__dirname}/src/posts`,
                name: `posts`,
            },
        },
        `gatsby-transformer-remark`,
        `gatsby-plugin-sass`
    ],
}

package.json:

{
    "name": "carusog",
    "description": "Giuseppe Caruso personal blog",
    "version": "1.0.0",
    "author": "Giuseppe Caruso <[email protected]>",
    "dependencies": {
        "gatsby": "next",
        "gatsby-image": "next",
        "gatsby-plugin-react-helmet": "next",
        "gatsby-plugin-sass": "next",
        "gatsby-plugin-sharp": "next",
        "gatsby-source-filesystem": "next",
        "gatsby-transformer-remark": "next",
        "node-sass": "^4.9.2",
        "react": "^16.4.1",
        "react-dom": "^16.4.1",
        "react-helmet": "^5.2.0"
    },
    "keywords": [
        "gatsby"
    ],
    "license": "MIT",
    "scripts": {
        "build": "gatsby build",
        "develop": "gatsby develop",
        "format": "prettier --write 'src/**/*.js'",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "devDependencies": {
        "prettier": "^1.12.0"
    }
}

gatsby-node.js:

/**
 * Implement Gatsby's Node APIs in this file.
 *
 * See: https://www.gatsbyjs.org/docs/node-apis/
 */

const path = require('path')

exports.createPages = ({ actions, graphql }) => {
    const { createPage } = actions
    const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)

    return graphql(`
        {
            allMarkdownRemark(
                sort: { order: DESC, fields: [frontmatter___date] },
                limit: 10
            ) {
                edges {
                    node {
                        html
                        id
                        frontmatter {
                            title
                            date
                            path
                            excerpt
                            tags
                        }
                    }
                }
            }
        }
    `)
    .then(result => {
        if (result.errors) {
            return Promise.reject(result.errors)
        }

        const posts = result.data.allMarkdownRemark.edges

        posts.forEach(({ node }, index) => {
            createPage({
                path: node.frontmatter.path,
                component: blogPostTemplate,
                context: {
                    // prev and next seem inverted but we must consider that being posts sorted
                    // by date, DESC, last one is actually first post and vice versa
                    next: index === 0 ? null : posts[index - 1].node,
                    prev: index === (posts.length - 1) ? null : posts[index + 1].node
                }
            })
        });
    })
}

gatsby-browser.js: N/A
gatsby-ssr.js: N/A

help wanted bug

Most helpful comment

Just a note that relay can pass the query from file to file without any issues.

We can expect people will want to write HOC to wrap the StaticQuery into a more usable function and we cannot do that unless the query can be passed around as a variable.

All 5 comments

Thanks @carusog!

I'm not 100% sure, but I have a theory on what's causing this.

In file-parser.js, it looks like we're traversing the AST to find StaticQuery components, then looking for graphql template tags inside. My theory is that this doesn't expand variables, so it never adds the query to the queue — and that's why it appears to be loading forever.

https://github.com/gatsbyjs/gatsby/blob/d8aaa2f346ea30fac760b0fb4359bb251779525a/packages/gatsby/src/internal-plugins/query-runner/file-parser.js#L86-L118

My theory is that this doesn't expand variables

That sounds right. We would need to add handling for variables and if we were to do that, what about importing queries from other files? This can quickly get very complex, so best short term course of action IMO would be display warning/error if we use graphql without template literals

Yeah, we should support pulling in a query defined in the same file — it shouldn't be too hard I don't think... if someone with some Babel experience wants to tackle it.

Just a note that relay can pass the query from file to file without any issues.

We can expect people will want to write HOC to wrap the StaticQuery into a more usable function and we cannot do that unless the query can be passed around as a variable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jimfilippou picture jimfilippou  Â·  3Comments

brandonmp picture brandonmp  Â·  3Comments

dustinhorton picture dustinhorton  Â·  3Comments

3CordGuy picture 3CordGuy  Â·  3Comments

Oppenheimer1 picture Oppenheimer1  Â·  3Comments