Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use GraphQL queries in a container class component

👋

My current GatsbyJS project is a one pager with a carousel and some other content.

Background

The carousel should be filled with information about some products. My goal is to let the carousel build itself by iterating through all markdown files, picking the ones with these three lines at the top of the file:

---
type: product
---

So I've created a CarouselContainer (class component) and a Carousel component (functional component). The Container should load the markdown via GraphQL query and pass the resulting products object to it's nested component. Then the component should map over the object and create the carousel.

But there are also other markdown files for menu lists, text modals and so on. They have the type: page. I thought preparing a few GraphQL queries would be the solution. But it turned out to be more difficult than expected...

The container component is a class component, so I am not able to call the query directly in it (https://github.com/gatsbyjs/gatsby/issues/3991#issuecomment-364939030).

Then I thought putting multiple queries into the pages/index.js could be the solution.

export const indexQuery = graphql`
query IndexQuery {
  allMarkdownRemark(filter: {frontmatter: {type: {eq: "page"}}}) {
    edges {
      node {
        frontmatter {
          title
          text
        }
      }
    }
  }
}
`

export const productsQuery = graphql`
query ProductsQuery {
  allMarkdownRemark(filter: {frontmatter: {type: {eq: "product"}}}) {
    edges {
      node {
        id
        frontmatter {
          title
          content
        }
      }
    }
  }
}
`

Nope again. Using GraphQL fragments should be a solution...

Q Can someone tell me how to prepare fragments for that purpose and/or have another idea how to get the markdown content right into my container?

Thanks for reading.

like image 881
Giregar Avatar asked Oct 12 '18 14:10

Giregar


People also ask

How do I get data from a GraphQL query?

You can fetch data very simply with the help of the package graphql-request . GraphQL Request is a library that doesn't require you to set up a client or a Provider component. It is essentially a function that just accepts an endpoint and a query.

How do you query in GraphiQL?

The GraphiQL client allows you to create variables for use in your queries. To add a query variable, click the Query Variables pane and enter a JSON object that defines your variable. To use a variable in your query, prepend the $ character to your variable name and use it to replace the desired value.


1 Answers

You're not too far off. GraphQL supports multiple discrete nodes being queried in the same query:

export const query = graphql`
  {
    products: allMarkdownRemark(
      filter: { frontmatter: { type: { eq: "product" } } }
    ) {
      edges {
        # ...
      }
    }

    pages: allMarkdownRemark(
      filter: { frontmatter: { type: { eq: "pages" } } }
    ) {
      edges {
        # ...
      }
    }
  }
`

Note that I've used aliases to fetch the same initial node (allMarkdownRemark) with separate filters in the same GraphQL query. This will result in data.products and data.pages being passed into your default exported React component.

To clean this up, you can use fragments, allowing you to colocate your products query in your Carousel file:

In carousel.js (or whatever file houses your Carousel component):

export const query = graphql`
  fragment Products on Query {
    products: allMarkdownRemark(
      filter: { frontmatter: { type: { eq: "product" } } }
    ) {
      edges {
        # ...
      }
    }
  }
`

Then in your page file:

export const query = graphql`
  {
    pages: allMarkdownRemark(
      filter: { frontmatter: { type: { eq: "pages" } } }
    ) {
      edges {
        # ...
      }
    }

    ...Products
  }
`

Note: if you're using Gatsby 1.x you'll need to change the on Query portion of the fragment to on RootQueryType.

Assuming you're using Gatsby v2, you can also use StaticQuery instead of combining the query into one. This is particularly useful if your pages have no bearing on the Carousel of products.

import React from "react";
import { graphql, StaticQuery } from "gatsby";

class Carousel extends React.Component {
  // ...
}

export default props => (
  <StaticQuery
    query={graphql`
      products: allMarkdownRemark(
        filter: { frontmatter: { type: { eq: "product" } } }
      ) {
        edges {
          # ...
        }
      }
    `}
    render={({ products }) => <Carousel products={products} {...props} />}
  />
);
like image 157
coreyward Avatar answered Oct 01 '22 22:10

coreyward