Gridsome: Context variable not passed to page-query

Created on 8 Jun 2019  路  3Comments  路  Source: gridsome/gridsome

Description

I can't access a primaryTag variable in my page-query.
What I want to achieve is on a blog Post page:

  • display the related posts (based on the first tag)

Steps to reproduce

In my gridsome.server.js

api.createPages(async ({ graphql, createPage }) => {
    // Use the Pages API here: https://gridsome.org/docs/pages-api
    const { data } = await graphql(`{
      allPost {
        edges {
          node {
            id
            path
            tags {
              id
            }
          }
        }
      }
    }`)

    data.allPost.edges.forEach(({ node }) => {
      createPage({
        path: `${node.path}`,
        component: './src/templates/Post.vue',
        context: {
          id: node.id,
          path: node.path,
          primaryTag: node.tags[0] || '',
        }
      })
    })
  })

then in my Post.vue

<page-query>
query Post ($path: String!, $primaryTag: String!) {
  post: post (path: $path) {
    title
    path
    content
  }
  related: allPost(
    filter: { tags: { contains: [$primaryTag] }, path: { ne: $path } }
  ) {
    edges {
      node {
        id
        title
        path
      }
    }
  }
}
</page-query>

also, I'm using this in gridsome.config.js:

plugins: [
    {
      use: '@gridsome/source-filesystem',
      options: {
        typeName: 'Post',
        path: 'content/posts/*.md',
        route: '/:slug',
        refs: {
          // Creates a GraphQL collection from 'tags' in front-matter and adds a reference.
          tags: {
            typeName: 'Tag',
            route: '/tag/:id',
            create: true,
          }
        },
      }
    }
  ],
  transformers: {
    remark: {
      externalLinksTarget: '_blank',
      externalLinksRel: ['nofollow', 'noopener', 'noreferrer'],
      anchorClassName: 'icon icon-link',
      plugins: [
        '@gridsome/remark-prismjs'
      ]
    }
  }

I guess it's maybe this one that conflict by creating the pages too?

Expected result

I could access my $primaryTag variable and everything is fine. :smile:

Actual result

Variable "$primaryTag" of non-null type "String!" must not be null. :cry:

Environment


Libs:
- gridsome version: 0.6.3
- @gridsome/cli version: 0.1.1


Browser:
- [x] Chrome (desktop) version 74
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

For Tooling issues:
- Node version: v8.12.0
- Platform:  Linux

Others:

I opened this [stackoverflow question](https://stackoverflow.com/questions/56479599/gridsome-context-variable-not-passed-to-page-query), so feel free to close and comment there if you prefer.

Most helpful comment

Can you try to change the name of the template file to something orther than Post.vue? Gridsome generates routes for it if the name matches a content type, but it will miss the primaryTag variable..

All 3 comments

Can you try to change the name of the template file to something orther than Post.vue? Gridsome generates routes for it if the name matches a content type, but it will miss the primaryTag variable..

Awesome @hjvedvik. That did solve my issue!
Thanks for the quick answer :tada:

Do you know if it's a best approach to retrieve the related posts or do you see another way of doing so?

Do you know if it's a best approach to retrieve the related posts or do you see another way of doing so?

I get all the posts (about 250 posts) in , then I filter them in computed.
I don't know if it's a better way 馃槀

computed: {
    getRelatedPost() {
      // create new array for easier filter
      const obj = this.$page.relatedPosts;
      var newArr = [];
      obj.edges.forEach(({ node }) => {
        newArr.push({
          id: node.id,
          title: node.title,
          timeToRead: node.timeToRead,
          date: node.date,
          path: node.path,
          categories: node.categories.map(el => el.title)
        });
      });
      // get current post's category
      const currentPostCategories = this.$page.post.categories.map(function(
        el
      ) {
        return el.title;
      });

      const filterArr = newArr.filter(function(el) {
        // check if an array contains any element of another array
        return currentPostCategories.some(r => el.categories.indexOf(r) >= 0);
      });

      // only get 10 related posts
      if (filterArr.length > 10) {
        return filterArr.slice(0, 10);
      }
      return filterArr;
    }
  },
Was this page helpful?
0 / 5 - 0 ratings