Graphql Query to extract post matching the current post category
See original GitHub issueI want to display related posts on each individual post page based on the current post category, below is my RecomendedPosts and gatsby-node file code. Currently I have hardcoded the category, how can I make it dynamic, please suggest.
`import React from 'react';
import { useStaticQuery, graphql, Link } from 'gatsby';
import Img from 'gatsby-image';
import '../templates/styles/articleStyles.css';
const RecomendedPosts = () => {
const data = useStaticQuery(graphql`
query {
allWordpressPost(filter: {categories: {elemMatch: {name: {eq: "General" }}}}, sort: { fields: [date], order: DESC }) {
edges {
node {
title
excerpt
slug
categories {
id
name
slug
}
featured_media {
source_url
localFile {
relativePath
childImageSharp {
resolutions(width: 350, height: 200) {
...GatsbyImageSharpResolutions_withWebp
src
width
height
}
}
}
}
}
}
}
}
`);
return (
<div className="container">
<div className="row">
<div className="col-sm-4 pr-sm-2" style={{ paddingRight: '40px' }} >
{data.allWordpressPost.edges[0].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[0].node.slug}/`} style={{ paddingTop: '50px' }} >
<Img resolutions={data.allWordpressPost.edges[0].node.featured_media.localFile.childImageSharp.resolutions} style={{ paddingRight: '40px' }}/>
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[0].node.slug}/`} style={{ paddingTop: '50px' }} >
<b>{data.allWordpressPost.edges[0].node.title}</b>
</Link>
</div>
<div className="col-sm-4 pl-sm-2" style={{ paddingRight: '40px' }}>
{data.allWordpressPost.edges[11].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[11].node.slug}/`}>
<Img resolutions={data.allWordpressPost.edges[11].node.featured_media.localFile.childImageSharp.resolutions} />
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[11].node.slug}/`}>
<b>{data.allWordpressPost.edges[11].node.title}</b>
</Link>
</div>
<div className="col-sm-4 pr-sm-2" style={{ paddingRight: '40px' }}>
{data.allWordpressPost.edges[2].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[2].node.slug}/`}>
<Img resolutions={data.allWordpressPost.edges[2].node.featured_media.localFile.childImageSharp.resolutions} />
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[2].node.slug}/`}>
<b>{data.allWordpressPost.edges[2].node.title}</b>
</Link>
</div>
</div>
<div className="row">
<div className="col-sm-4 pr-sm-2" style={{ paddingRight: '40px' }} >
{data.allWordpressPost.edges[8].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[8].node.slug}/`} >
<Img resolutions={data.allWordpressPost.edges[8].node.featured_media.localFile.childImageSharp.resolutions} />
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[8].node.slug}/`} >
<b>{data.allWordpressPost.edges[8].node.title}</b>
</Link>
</div>
<div className="col-sm-4 pl-sm-2" style={{ paddingRight: '40px' }}>
{data.allWordpressPost.edges[5].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[5].node.slug}/`}>
<Img resolutions={data.allWordpressPost.edges[5].node.featured_media.localFile.childImageSharp.resolutions} />
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[5].node.slug}/`}>
<b>{data.allWordpressPost.edges[5].node.title}</b>
</Link>
</div>
<div className="col-sm-4 pr-sm-2" style={{ paddingRight: '40px' }}>
{data.allWordpressPost.edges[6].node.featured_media.localFile.childImageSharp.resolutions != null &&
<div className="img-responsive" style={{ width: '244px', height: '200px'}}>
<Link to={`/blogs/${data.allWordpressPost.edges[6].node.slug}/`}>
<Img resolutions={data.allWordpressPost.edges[6].node.featured_media.localFile.childImageSharp.resolutions} />
</Link>
</div>
}
<Link to={`/blogs/${data.allWordpressPost.edges[6].node.slug}/`}>
<b>{data.allWordpressPost.edges[6].node.title}</b>
</Link>
</div>
</div>
</div>
);
};
export default RecomendedPosts;`
`const path = require('path');
const slash = require('slash');
const _ = require('lodash');
const { paginate } = require('gatsby-awesome-pagination');
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const pageTemplate = path.resolve('./src/templates/page.js');
const archiveTemplate = path.resolve('./src/templates/archive.js');
const postTemplate = path.resolve('./src/templates/post.js');
const result = await graphql(`
{
allWordpressPage {
edges {
node {
id
status
link
wordpress_id
wordpress_parent
}
}
}
allWordpressPost(filter: {status: {eq: "publish"}}, sort: {order: DESC, fields: date}, limit: 1000 ) {
edges {
node {
id
link
status
categories {
id
name
slug
}
featured_media {
localFile{
childImageSharp {
id
}
}
}
}
}
}
allWordpressCategory {
edges {
node {
id
name
slug
count
}
}
}
allSite {
edges {
node {
siteMetadata {
title
description
author
}
}
}
}
site {
siteMetadata {
domain: siteUrl
}
}
}
`);
// Check for errors
if (result.errors) {
throw new Error(result.errors);
}
const {
allWordpressPage,
allWordpressPost,
allWordpressCategory,
} = result.data;
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
devtool: "eval-source-map"
});
};
// Create archive pages for each category
allWordpressCategory.edges.forEach(catEdge => {
// First filter out the posts that belongs to the current category
const filteredPosts = allWordpressPost.edges.filter(
({ node: { categories } }) =>
categories.some(el => el.id === catEdge.node.id)
);
// Some categories may be empty and we don't want to show them
if (filteredPosts.length > 0) {
paginate({
createPage,
items: filteredPosts,
itemsPerPage: 10,
pathPrefix:
catEdge.node.slug === "blogs"
? "/blogs"
: `/blogs/${catEdge.node.slug}`,
component: slash(archiveTemplate),
context: {
catId: catEdge.node.id,
catName: catEdge.node.name,
catSlug: catEdge.node.slug,
catCount: catEdge.node.count,
categories: allWordpressCategory.edges,
},
});
}
});
allWordpressPage.edges.forEach(edge => {
if (edge.node.status === 'publish') {
createPage({
path: edge.node.link,
component: slash(pageTemplate),
context: {
id: edge.node.id,
parent: edge.node.wordpress_parent,
wpId: edge.node.wordpress_id,
},
});
}
});
/*const {posts} = result.data.allWordpressPost.edges*/
_.each(result.data.allWordpressPost.edges, edge =>{
createPage({
path: `/blogs${edge.node.link}`,
component: slash(postTemplate),
context: {
id: edge.node.id,
},
});
});
};
`
Summary
Relevant information
Environment (if relevant)
File contents (if changed)
gatsby-config.js
: N/A
package.json
: N/A
gatsby-node.js
: N/A
gatsby-browser.js
: N/A
gatsby-ssr.js
: N/A
Issue Analytics
- State:
- Created 4 years ago
- Comments:17 (2 by maintainers)
Top Results From Across the Web
Getting the categoryId of a post in Graphql
This is my Graphql query for getting posts from headless wordpress: export const GET_POSTS = gql` query GET_POSTS( $uri: String, ...
Read more >GraphQL Search and Filter – How to ...
The goal is to find an item (or a list of items) that matches some sort of criteria. For the rest of this...
Read more >How to query some posts and then get all their categories
I only get the first category listed for each post. Is there a way to get all of them? Thanks for any advice....
Read more >Search and Filtering - GraphQL
Get a single object; Query a list of objects; Query that filters objects by ... In the query below, we fetch posts that...
Read more >GraphQL Query Options
In this query the fields categories and title are filtered to find the book that belongs to the magical creatures category AND has...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@vladar just like every issue i pick up, i tend to give the person the most accurate and most complete answer so that he/she can go through it at his/her own pace and with that learn a bit more about the framework. In this particular i presented a couple of ways this could be fixed
@expatguideturkey i’ve cloned your repo and i think i have a solution for your issue. I’m going to detail it below, and with that give you two options on how you could proceed.
src\templates\post.js
and the componentsrc\components\RecomendedPost.js
and part of the issue lies there, @vladar mislead you inadvertly, by sugesting the code change, as when i read the description he assumed that theRecomendedPosts.js
was actually a page component/template, so that’s why he sugested you use it.gatsby-node.js
file and you the change i mentioned was still not applied, probably you did not commit it yet.Now for the options that i’ve mentioned.
In this case you can go about it by doing the following:
gatsby-node.js
file to the following (i’m leaving out the graphql and “imports” for brevity purposesAs you can see the webpack config api hook is in it’s correct place and also if you check the comments i left in, you’ll see that you trying to add a element to Gatsby special prop
context
that is not correct, you’re trying to addcatId
as a single item, when what is actually returned from the query is a array. This might work while you’re developing the app/site with Gatsby develop, as Gatsby is way more permissive and let’s you “get away with it” (pardon the bad pun) but things might become more interesting when you switch to production. Getting build errors and with that you’ll waste time tracking them down. Also you might have noticed the introduction ofcategoryList
, this element will be injected into page, it will grab each category id that is associated to the page and it will used as a graphql query variable, you’ll see that shortly.src\templates\post.js
i made a couple changes to it and it now looks like the following:Key things to take from this, the query is changed to fetch not only the post and also the related posts associated with it based on the query result, which is aliased by
relatedPosts
.src\components\RecomendedPosts.js
to the following:I left in some comments, but as you can see it’s now a fully functional component that “his job” is to render the information available, i left in a "sanity check " just to make sure that it doesn’t blow up in case of the
relatedPosts
prop is null.yarn develop
(i’m using yarn, if you use npm adjust accordingly) to generate a development build and i opened up the site and a random blog entry and i’m presented with the following:On the left side is the entry with the associated posts, and on the right side one item opened based the one on the left.
Now for the second option.
gatsby-node.js
file, as you already have all the information at your disposal, we can streamline the process of getting the related posts associated to a particular entry. As the information that is required is small, you can do the following change:Key things to take from this, i created a small auxiliary function to filter out the posts that are fetched from your cms, more specifically the function
getRelatedPosts
and like above i left out the graphql query and imports for brevity purposes. I would like to point out that this is not “battle tested”(pardon the bad pun) and probably you can fine tune this better. Performance wise, i much rather prefer to “take a hit” (once again pardon the bad pun) in here than later. This could be even be more improved, by fetching all the data ingatsby-node.js
and injecting it into the template, making it a fully presentational component. But i’ll leave that to you to consider.Moving on…
src\templates\post.js
was changed back to it’s original form, with the caveat that the related posts will passed down via props based on what’s inpageContext
:And with this change the
src\components\RecomendedPosts.js
was changed a bit to the following:Key thing to take from this change is the following, right now i’m showing the link, as techically i don’t have a title element present in the recomended posts, that’s why i’m showing the link instead.
This could be adjusted to show all the information required, by updating the query in
gatsby-node.js
. I’ll leave it up to you on how you wish to procceed.I’m really sorry for taking to much time answering, but i was sidetracked with some real life items that need to be addressed and ended up taking way too long. Also i would like to appologize for the extreme long post, but i would like to give you the best answer i could so that the issue could be solved.
Feel free to provide feedback so that we can close this issue, or continue to work on it until we find a suitable solution.