0

I want to choose just featured posts (3 posts) from graphql for then show this in my blog page, so I limit query to only three results but in case that I just have one post the site will fail.

Because, I'm using a staticquery for get data, in this case I should to use render attribute in the staticquery component and I can not to use a if block on the attribute and when graphql won't find other posts it gonna fail.

Here the code:

featured-posts.js

import React from "react"
import MiniFeatured from "../components/minifeatured"
import { StaticQuery, Link, graphql } from "gatsby"

const Featured = () => {
    return (
        <StaticQuery
            query={graphql`
                query FeaturedBlogsport {
                    allMarkdownRemark (
                        limit: 3
                        sort: {order: DESC, fields: [frontmatter___date]}
                        filter: {frontmatter: {featured: {eq: true}}}
                    ) {
                        edges {
                            node {
                                frontmatter {
                                    title
                                    description
                                    post_image
                                }
                                fields {
                                    slug
                                }
                            }
                        }
                    }
                }               
            `}
            render={data => (
                <div className="mainBlogposts">
                    <div 
                        className="featuredBlogpost"
                        style={{backgroundImage: `url('${data.allMarkdownRemark.edges[0].node.frontmatter.post_image}')`}}    
                    >
                        <div className="featuredBlogpostContent">
                            <Link to={`https://strokequote.co/${data.allMarkdownRemark.edges[0].node.fields.slug}`}>
                                <h1 className="featuredBlogpostTitle">
                                    {data.allMarkdownRemark.edges[0].node.frontmatter.title}
                                </h1>
                                <h6 className="featuredBlogpostAuthor">
                                    {data.allMarkdownRemark.edges[0].node.frontmatter.description}
                                </h6>
                            </Link>
                        </div>
                    </div>
                    <div className="minifeaturedBlogpostsContainer">
                        <MiniFeatured
                            title={data.allMarkdownRemark.edges[1].node.frontmatter.title}
                            description={data.allMarkdownRemark.edges[1].node.frontmatter.description}
                            postImage={data.allMarkdownRemark.edges[1].node.frontmatter.post_image}
                            slug={data.allMarkdownRemark.edges[1].node.fields.slug}
                        />

                        <MiniFeatured
                            title={data.allMarkdownRemark.edges[2].node.frontmatter.title}
                            description={data.allMarkdownRemark.edges[2].node.frontmatter.description}
                            postImage={data.allMarkdownRemark.edges[2].node.frontmatter.post_image}
                            slug={data.allMarkdownRemark.edges[2].node.fields.slug}
                        />
                    </div>
                </div>
            )}
        />
    )
}

export default Featured

PDD. Minifeatured are secondary featured posts in other components. PDD 2. Sorry about my English, I'm still learning

2
  • Does this answer your question? Rendering an array.map() in React Commented Jul 2, 2020 at 5:18
  • @ksav no exactly because, although it helps me Commented Jul 2, 2020 at 11:25

2 Answers 2

1

I believe that find found a solution. With useStaticQuery from gatsby I can do something like this:

const Featured = () => {
    const { edges } = FeaturedPostsQuery()
    return (
        <div className="mainBlogposts">
            <div 
                className="featuredBlogpost"
                style={{backgroundImage: `url('${edges[0].node.frontmatter.post_image}')`}}    
            >
                <div className="featuredBlogpostContent">
                    <Link to={`https://strokequote.co/${edges[0].node.fields.slug}`}>
                        <h1 className="featuredBlogpostTitle">
                            {edges[0].node.frontmatter.title}
                        </h1>
                        <h6 className="featuredBlogpostAuthor">
                            {edges[0].node.frontmatter.description}
                        </h6>
                    </Link>
                </div>
            </div>
            <div className="minifeaturedBlogpostsContainer">
                <MiniFeatured
                    title={edges[1].node.frontmatter.title}
                    description={edges[1].node.frontmatter.description}
                    postImage={edges[1].node.frontmatter.post_image}
                    slug={edges[1].node.fields.slug}
                />

                <MiniFeatured
                    title={edges[2].node.frontmatter.title}
                    description={edges[2].node.frontmatter.description}
                    postImage={edges[2].node.frontmatter.post_image}
                    slug={edges[2].node.fields.slug}
                />
            </div>
        </div>
    )
}

export default Featured

export const FeaturedPostsQuery = () => {
    const { allMarkdownRemark } = useStaticQuery(graphql`
        query FeaturedBlogsport {
            allMarkdownRemark (
                limit: 3
                sort: {order: DESC, fields: [frontmatter___date]}
                filter: {frontmatter: {featured: {eq: true}}}
            ) {
                edges {
                    node {
                        frontmatter {
                            title
                            description
                            post_image
                        }
                        fields {
                            slug
                        }
                    }
                }
            }
        }  
    `)

    return allMarkdownRemark
}

Sign up to request clarification or add additional context in comments.

1 Comment

You should use conditions like {edges[1] && <MiniFeatured ... everywhere ... what if edges will be null, empty array or no edges[2] ?
0

Why do you use a StaticQuery to achieve this? You can simply do it by using a regular GraphQL query, like:

import { graphql, Link } from 'gatsby';
import React from 'react';

const Featured = ({ data }) => {
  return <div>
    {data.allMarkdownRemark.edges.map(({ node: post }) => {
      return <div className="mainBlogposts">
        <div className="featuredBlogpost"
             style={{ backgroundImage: `url(${post.frontmatter.post_image})` }}>
          <div className="featuredBlogpostContent">
            <Link to={`https://strokequote.co/${post.fields.slug}`}>
              <h1 className="featuredBlogpostTitle">
                {post.frontmatter.title}
              </h1>
              <h6 className="featuredBlogpostAuthor">
                {post.frontmatter.description}
              </h6>
            </Link>
          </div>
        </div>
      </div>;
    })}
  </div>;
};

export const AboutMeData = graphql`    
    query FeaturedBlogsport {
        allMarkdownRemark (
            limit: 3
            sort: {order: DESC, fields: [frontmatter___date]}
            filter: {frontmatter: {featured: {eq: true}}}
        ) {
            edges {
                node {
                    frontmatter {
                        title
                        description
                        post_image
                    }
                    fields {
                        slug
                    }
                }
            }
        }
    }
`;

What I've done is simply get all the 3 articles and loop through them, using your HTML structure. I aliased the node as a post using a destructuring inside the iterable variable in { node: post } but ideally, all that bunch of HTML should be another isolated component (it's really huge) and you should pass post as a prop to them but for now, it will work.

The snippet above will simply print the amount of post that the query can fetch, no matter if it's 1, 2, or 3.

Besides, it's cleaner than accessing manually each array position ([0], [1], etc).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.