📅 November 20, 2018
👷 Chris Power
This blog and website are built on React using a static site framework called Gatsby. Recently, I wanted to add a new component to this site to display the latest 3 blog posts on the index page (hey, this may be one of the blog posts being diplayed right now!). I thought this would be a great opportunity to show what its like to make a React component in a Gatsby site, along with a little GraphQL work. We create a new component in our site, grab some data with GraphQL, and display it all on the home page! Alright, enough about me, lets get to business. clears throat.
Gatsby is a static site generator built using React. With Gatsby, you get the power and flexibility of React, while enjoying the benefits of a static website. Gatsby bundles up a lot of great technologies to get you started with your static website: server side rendering, a vibrant plugin ecosystem, and multiple starter kits. With Gatsby, you also get a fun querying technology called GraphQL. We won’t touch on too much information about GraphQL in this post, but we will brush over it slightly — as if we were dancing with it, and didn’t want to be too rude.
When building a new component, sometimes I like to write the code inline, just
to prove out the concept of what I want to do. Lets start by writing our three
blog posts in a variable (don’t worry, we’ll actually fetch the data later
with GraphQL). We assume we’ll have a title
and an excerpt
for these posts:
const someArrayOfPosts = [
{ title: 'some title for post 1', excerpt: 'this is an excerpt for post one' },
{ title: 'some title for post 2', excerpt: 'this is an excerpt for post two' },
{ title: 'some title for post 3', excerpt: 'this is an excerpt for post three' }
]
Then, lets display these posts somewhere in a render function:
{someArrayOfPosts.map(post => (
<div class="card">
<div class="card-title">
{post.title}
</div>
<div class="card-body">
{post.excerpt}
</div>
</div>
))}
Great! You now have three posts displaying somewhere.
Lets now create a component with the simple code we just inline’d. In my setup,
I write a component to a file like: src/components/ComponentName/index.js
. So
lets create a new component:
import React from 'react';
const { Component } = React;
class BlogPostPreview extends Component {
render() {
const { title, excerpt } = this.props;
return (
<div className="col-12 col-md-4 mb-4">
<div className="card blog-post-preview">
<div className="card-header font-weight-bold">
{title}
</div>
<div className="card-body text-left">
{excerpt}
</div>
</div>
</div>
);
}
};
export default BlogPostPreview;
I’m expecting that we pass in our title
and excerpt
in as props. With this
component created, lets replace our previous inline’d code in our home page:
import BlogPostPreview from '../components/BlogPostPreview';
then later…
{posts.map(post => (
<BlogPostPreview
title={post.title}
excerpt={post.excerpt}
/>
))}
Cool! We’re getting somewhere
Now we want to fetch the posts with the GraphQL server built into Gatsby. To do this, we need to add a query to the index page where we’re rendering these posts:
export const pageQuery = graphql`
query PostPreviewQuery {
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }, limit: 3) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`
I haven’t checked the docs, but I assume pageQuery
is something Gatsby hooks
into, in order to run a query on a page. We name this query PostPreviewQuery
,
we sort by our frontmatter date
. and we limit our post count to 3.
Quick note about that frontmatter stuff: We are grabbing markdown posts stored in
pages/blog/PostTitle/post.md
. These markdown files have a structure at the top
describing their date, title, and image. This structure is called frontmatter
,
and the gatsby transformer
remark package
helps us query this frontmatter
.
our page query returns posts in a format like this:
[
{ node: { data } }
]
So now we can replace our data passed into the component with the new posts from our GraphQL query:
const posts = get(this, 'props.data.allMarkdownRemark.edges');
{posts.map(post => (
<BlogPostPreview
title={post.node.frontmatter.title}
excerpt={post.node.excerpt}
/>
))}
And there you have it. A new component rendering data you grabbed from GraphQL.
We're trusted by large, medium, and small companies all over the world
Have something you're working on?
Tell Us About It