user12207614
user12207614

Reputation:

Conditional rendering in React + Gatsby Static Query + GraphQL

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

Upvotes: 0

Views: 1007

Answers (2)

Ferran Buireu
Ferran Buireu

Reputation: 29320

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).

Upvotes: 0

user12207614
user12207614

Reputation:

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
}

Upvotes: 1

Related Questions