gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.28k stars 10.31k forks source link

Using GraphQL filters with mdx #21415

Closed tristpc closed 4 years ago

tristpc commented 4 years ago

Description I am programmatically creating pages in gatsby-node and passing page context for these so that the graphQL query works in each template. The filter currently is of the form:-

query($tag: String, $place: String) { posts: allMdx( filter: {frontmatter: {tags: { in: [$tag] } meeting: { eq: $place } }} )

This works, but the problem is that I have to use 4 templates where the only difference is the filter. So instead I am trying to generate $filter in gatsby-node but am getting errors. I have only found bits of info on this issue when searching online.

This is what I have tried:- In gatsby-node:- context: { filter: '{frontmatter: {tags: { in: ["'+item+'"] } meeting: { eq: "'+element+'" } }}', }

In the template:- query($filter: MdxFilterInput) { posts: allMdx( filter: $filter )

Expected result If set up and working correctly, only 1 template will be needed, and the filter will be tailored for each page within gatsby-node.

What actually happens: the error On running gatsby develop, this is the error message:- "Variable "$filter" got invalid value "filter: {frontmatter: {tags: { in: [\"Adventure\"] } meeting: { eq: \"Central Pacific\" } }}"; Expected type MdxFilterInput to be an object."

I have also tried MdxFrontmatterFilterInput but the error message was "Expected type MdxFilterInput to be an object."

It looks if either the way of creating the filter in gatsby-node is wrong, or I am using the wrong definition (eg MdxFilterInput) for the filter in the template.

Steps to reproduce Public repo is https://github.com/tristpc/seedrez10 I have only been developing this via Gitpod, ie online.

gatsby info --clipboard (from running in gitpod) System: OS: Linux 4.14 Ubuntu 19.04 (Disco Dingo) CPU: (16) x64 Intel(R) Xeon(R) CPU @ 2.20GHz Shell: 5.0.3 - /bin/bash Binaries: Node: 10.18.0 - ~/.nvm/versions/node/v10.18.0/bin/node Yarn: 1.21.1 - ~/.nvm/versions/node/v10.18.0/bin/yarn npm: 6.13.4 - ~/.nvm/versions/node/v10.18.0/bin/npm Languages: Python: 2.7.17 - /home/gitpod/.pyenv/shims/python npmPackages: gatsby: ^2.3.25 => 2.17.6 gatsby-image: ^2.0.39 => 2.2.30 gatsby-plugin-feed: ^2.1.1 => 2.3.19 gatsby-plugin-google-analytics: ^2.0.18 => 2.1.23 gatsby-plugin-manifest: ^2.0.29 => 2.2.25 gatsby-plugin-mdx: ^1.0.52 => 1.0.54 gatsby-plugin-netlify-cms: ^4.0.0 => 4.1.26 gatsby-plugin-netlify-identity: 0.0.3 => 0.0.3 gatsby-plugin-offline: ^2.0.25 => 2.2.10 gatsby-plugin-react-helmet: ^3.0.12 => 3.1.13 gatsby-plugin-sharp: ^2.0.35 => 2.2.34 gatsby-plugin-styled-components: ^3.0.7 => 3.1.11 gatsby-plugin-typography: ^2.2.13 => 2.3.15 gatsby-remark-copy-linked-files: ^2.0.11 => 2.1.28 gatsby-remark-images: ^2.0.6 => 2.0.6 gatsby-remark-responsive-iframe: ^2.1.1 => 2.2.25 gatsby-remark-smartypants: ^2.0.9 => 2.1.14 gatsby-remark-vscode: ^1.0.4 => 1.2.1 gatsby-source-filesystem: ^2.0.29 => 2.1.35 gatsby-transformer-remark: ^2.3.8 => 2.6.32 gatsby-transformer-sharp: ^2.1.18 => 2.3.1 npmGlobalPackages: gatsby-cli: 2.8.29

LekoArts commented 4 years ago

Thank you for opening this!

What you're trying to do is not possible. You can't pass in the filter via a variable and then somehow construct those 4 separate queries. You'll need to write them out individually. I'd recommend using Fragments to not repeat yourself too much: https://www.gatsbyjs.org/docs/using-graphql-fragments/

We're marking this issue as answered and closing it for now but please feel free to comment here if you would like to continue this discussion. We also recommend heading over to our communities if you have questions that are not bug reports or feature requests. We hope we managed to help and thank you for using Gatsby!

tristpc commented 4 years ago

@LekoArts thanks for the reply. I believe I am trying to implement "query variables" and may not have explained myself well as you say "somehow construct those separate queries".

In fact constructing those separate queries would be take place in gatsby-node.js not the template page. The method I was trying would have included in gatsby-node.js createPage commands like these 3:-

createPage({ path: "/"+place+"/"+tag+"/", component: path.resolve(src/templates/TourList.js), context: { filter: '{frontmatter: {tags: { in: ["'+tag+'"] } meeting: { eq: "'+place+'" } }}', *** } })

createPage({ path: "/"+place+"/", component: path.resolve(src/templates/TourList.js), context: { filter: '{frontmatter: {meeting: { eq: "'+place+'" } }}', *** } })

createPage({ path: "/all/", component: path.resolve(src/templates/TourList.js), context: { filter: ' {frontmatter: {contentClass: {eq: "tour" } }}', *** } })

All would use the same template, TourList.js, but the filter in TourList.js would change as defined above. In TourList.js the graphql would have this:- filter: $filter

But it is not working, possibly because the filter input (eg MdxFrontmatterFilterInput) is wrong, or the definitions of the filters above are totally wrong. The latter (***) looks most certain.

But surely this should be possible if this is what "query variables" is all about? Or is there really no hope?