Dynamic Blog Using React.JS and GraphQL


Dynamic Blog Using React.JS and GraphQL

Recipe ID: hsts-r7


Self-paced training

We offer HTML5, CSS3, JavaScript,Bootstrap, Angular.JS, WordPress Node.JS, React.JS, Joomla, Drupal, Vue.JS and more classes in self-paced video format starting at $60. Click here to learn more and register. For complete self-paced web design training, visit our Web design and development bundle page.


Download source files for this recipe


In this tutorial recipe we are going to show you how to create a simple blog using React, GraphQL and Cosmic JS. This is going to be the fastest and most light-weight blog built on a modern technology stack.
Learning Objectives
This recipe explains how to use:

• GraphQL
• How to install next routes for dynamic routes
• Express.js for our server-side web app framework.
• Next.js as our React Universal framework.
• Axios for our promise-based HTTP client to get content from to the Cosmic JS GraphQL API.

Pre-Requisites
• Node.js installed locally
• Make sure you have yarn installed globally
• You should have understanding of JavaScript & GraphQL

Steps
Make sure that you have Node.js and NPM installed on your machine, if not, visit the Node.js website to install the latest version.
Let’s start by creating a folder for our app. In your favorite terminal run the following commands:
mkdir simple-react-blog
cd simple-react-blog
Now let’s add a package.json file to import all of our dependencies for our app:
vim package.json
Add the following to our package.json file:

It’s a pretty light dependency list for a pretty light app. So what we will install is:
1. Axios for our promise-based HTTP client to get content from to the Cosmic JS GraphQL API.
2. Next.js as our React Universal framework.
3. Next routes for dynamic routes.
4. Express for our server-side web app framework.
5. React to handle our user interface.
Our scripts are necessary for starting our app in production and development.
Run the following command to install our dependencies:
npm i
Building Our Blog
Next, let’s begin building our blog pages. Create a pages folder and add the index.js file:
vim index.js
and add the following to index.js:
import axios from 'axios'
import _ from 'lodash'
import Footer from './partials/footer'
import Header from './partials/header'
import helpers from '../helpers'
import config from '../config'

export default class extends React.Component {
static async getInitialProps({ req }) {
const query = `{
objects(bucket_slug: "${config.bucket.slug}") {
_id
type_slug
slug
title
metadata
created_at
}
}`
return await axios.post(`https://graphql.cosmicjs.com/v1`, { query })
.then(function (response) {
return {
cosmic: {
posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug')
}
}
})
.catch(function (error) {
console.log(error)
})
}
render() {
if (!this.props.cosmic)
return <div>Loading...</div>
return (
<div>
<Header cosmic={ this.props.cosmic }/>
<main className="container">
{
this.props.cosmic.posts &&
this.props.cosmic.posts.map(post => {
const friendly_date = helpers.friendlyDate(new Date(post.created_at))
post.friendly_date = friendly_date.month + ' ' + friendly_date.date
return (
<div className="card" data-href={`/${post.slug}`} key={post._id}>
{
post.metadata.hero.imgix_url &&
<a href={`/${post.slug}`} className="blog-post-hero blog-post-hero--short" style={{ backgroundImage: `url(${post.metadata.hero.imgix_url})`}}></a>
}
<div className="card-padding">
<h2 className="blog__title blog__title--small">
<a href={`/${post.slug}`}>{post.title}</a>
</h2>
<div className="blog__author">
<a href={`/author/${post.metadata.author.slug}`}>
<div className="blog__author-image" style={{ backgroundImage: `url(${post.metadata.author.metafields[0].imgix_url}?w=100)`}}></div>
</a>
<div className="blog__author-title">by <a href={`/author/${post.metadata.author.slug}`}>{post.metadata.author.title}</a> on {post.friendly_date}</div>
<div className="clearfix"></div>
</div>
<div className="blog__teaser droid" dangerouslySetInnerHTML={{__html: post.metadata.teaser}}></div>
<div className="blog__read-more">
<a href={`/${post.slug}`}>Read more...</a>
</div>
</div>
</div>
)
})
}
</main>
<Footer />
</div>
)
}
}

here are a few things happening here:
1. We are importing our essential modules: Axios, Lodash, and other helpers and components.
2. We are pulling in some partials: Header and Footer.
3. We query the Cosmic JS GraphQL API to only return the stuff we need: _id, type_slug, slug, title, metadata and created_at.
4. We set the main props in our component to the `cosmic` object. And use lodash to parse through Posts and Global Object types.
5. We return our posts array data and image URLs into our main blog feed.
Single Post Query
For our single post, we add a `post` property to our props. Post is found by matching the query.slug to the Object slug:
const gql_query = `{
objects(bucket_slug: "${config.bucket.slug}") {
type_slug
slug
title
content
metadata
created_at
}
}`
return await axios.post(`https://graphql.cosmicjs.com/v1`, { query: gql_query })
.then(function (response) {
return {
cosmic: {
posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug'),
post: _.find(response.data.data.objects, { slug: query.slug }),
}
}
})
.catch(function (error) {
console.log(error)
})
}

Conclusion
This is the simple Blog app created with React and GraphQL. We have also used some libraries like next.js and express.

Related Tutorials

Related Training Courses

PHP and MySQL Coding
Cross-platform Native App Development Using HTML5, CSS3 and JavaScript
Advance JavaScript, jQuery Using JSON and Ajax
Advance Website Design Using HTML and CSS


Private and Custom Tutoring

We provide private tutoring classes online and offline (at our DC site or your preferred location) with custom curriculum for almost all of our classes for $50 per hour online or $75 per hour in DC. Give us a call or submit our private tutoring registration form to discuss your needs.


View Other Classes!