Gatsby: GraphQL in every component?

Created on 19 Sep 2017  Â·  11Comments  Â·  Source: gatsbyjs/gatsby

Hi,

it is possible to use GraphQL in every component? I've read the tutorial about GraphQL in gatsby (https://www.gatsbyjs.org/tutorial/part-four/), there is explained how to use GraphQL in an layout/page file.

But for example: i've a page called "home" and one page "about". On each page there is an sidebar with an list of recent blog-posts. I would build an component "RecentBlogPosts", but i would avoid to query the blog posts in every page and pass it to the component. Instead it would be nice to query the blog posts in the "RecentBlogPosts" component.

I've tried to export an query in the component, but it didn't work (see snippet below).

import React from 'react';

const RecentBlogPosts = (props) => {
  console.log('props', props);

  return (
    <div>
      <h1>Blog-Posts</h1>
    </div>
  );
};

export const query = graphql`
  query Items {
    site {
      siteMetadata {
        title
        description
        keywords
      }
    }
  }
`;

export default RecentBlogPosts;

Many thanks!

question or discussion

Most helpful comment

It's specific to Gatsby. Gatsby needs to know when to load data. It does that by tying data to pages (and layouts) so it can know if a user is visiting page x, it needs to load the data associated with page x.

This is why pages are the "root" of the GraphQL queries.

Relay does something similar except the "roots" are arbitrary.

Apollo is more freeform (as I understand it — I haven't used it) and uses a system-wide runtime aggregation to combine requests.

All 11 comments

you can query in layouts

Ok. In components it is not possible?

You can but you need to compose the fragments into the top level query. I'm on a phone so I can't type out an example but check out the relay modern docs for composition (we use their compiler) as well as the gatsby doc site source code which uses this pattern

@jquense Any chance you have time to elaborate now?

I looked through various pieces of Gatsby components with GraphQL queries that are not pages and I don't see how the example here or my own code is any different. Something is just not clicking on my end.

@dlindahl Have you looked at the usage of fragments by several of the example sites?

I just took a look at ReasonML's site, specifically the GuideSidebar. It looks like the pattern is to define the desired query as a _fragment_ which is then referenced by the root node:

// in src/components/MyComponent.js
const MyComponent = () => <div/>

export default MyComponent

export const myQuery = graphql`
  fragment posts on RootQueryType {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`

// in src/pages/index.js
const Homepage = ({ data }) => <div/>

export default Homepage

export const query = graphql`
  query HomepageQuery {
    ...posts
  }
`

While I sort of understand how that is working, it is not quite the same as supporting GraphQL on any component. To elaborate, I'm trying to do something like:

// in src/provider/PostsProvider.js
const PostsProvider = ({ children, data }) => {
  const posts = data.allMarkdownRemark.edges.map((edge) => edge.node)
  return children(posts)
}

export default PostsProvider

export const query = graphql`
  query PostsQuery {
    allMarkdownRemark {
      totalCount
      edges {
        node {
          id
          frontmatter {
            title
            date
          }
          excerpt
        }
      }
    }
  }
`

// in src/pages/index.js
import PostsProvider from '../providers/PostsProvider'

const Homepage = (props) => (
  <div>
    <PostsProvider>
      {(posts) => posts.map(({ title })=> (
        <div>{title}</div>
      ))}
    </PostsProvider>
  </div>
)

Is such a pattern not supported here? If not, is that due to how Gatsby is meant to be used or is it something specific to GraphQL?

It's specific to Gatsby. Gatsby needs to know when to load data. It does that by tying data to pages (and layouts) so it can know if a user is visiting page x, it needs to load the data associated with page x.

This is why pages are the "root" of the GraphQL queries.

Relay does something similar except the "roots" are arbitrary.

Apollo is more freeform (as I understand it — I haven't used it) and uses a system-wide runtime aggregation to combine requests.

I've just stumbled across this as i'm trying to create a navigation component that is referenced in the layout and i can't get this to work. Wondering about how fragment works. Is there any examples?

I thought this was weird in the beginning, but got to like fragments more and more, feels like having more control of what loads what

but am always open to new approaches and ways ;)

Closing this as there's no action to be taken.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

signalwerk picture signalwerk  Â·  3Comments

3CordGuy picture 3CordGuy  Â·  3Comments

magicly picture magicly  Â·  3Comments

mikestopcontinues picture mikestopcontinues  Â·  3Comments

Oppenheimer1 picture Oppenheimer1  Â·  3Comments