Reputation: 11
I'm building a simple blog with GatsbyJS using Contentful. I have a blogpage with the list of all posts with titles and dates. I want to add, just for the last post, the first lines of the article and the image used in the article.
...
import React from 'react'
import Layout from '../components/layout'
import { Link, graphql, useStaticQuery } from 'gatsby'
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import blogStyles from './blog.module.scss'
import Head from '../components/head'
import TransitionLink from "gatsby-plugin-transition-link"
import AniLink from "gatsby-plugin-transition-link/AniLink"
const BlogPage = () => {
const data = useStaticQuery(graphql`
query{
allContentfulBlogPost (sort: { fields: publishedDate, order: DESC}){
edges{
node{
title
slug
publishedDate(formatString:"MMMM Do, YYYY")
}
}
}
}
`)
return (
<Layout>
<Head title = "Post" />
<h1>Post</h1>
<ol data-sal="slide-up" data-sal-delay="300" data-sal-easing="ease"
className={blogStyles.posts}>
{data.allContentfulBlogPost.edges.map((edge) => {
return (
<li className={blogStyles.post}>
<Link to={`/blog/${edge.node.slug}`}>
<h2>{edge.node.title}</h2>
<p>{edge.node.publishedDate }</p>
</Link>
</li>
)
})}
</ol>
</Layout>
)
}
export default BlogPage
Upvotes: 1
Views: 94
Reputation: 20821
Note: I've assumed you mean latest post, instead of last post.
You could use Aliases to split your query into two parts.
latestArticle
has a limit: 1
and queries for the extra fields needed for the first lines of the article and the image used in the article (as well as title, slugExt, publishDate
).
allOtherArticles
has a skip: 1
and just queries for title, slugExt, publishDate
.
const BlogPage = () => {
const { latestArticle, allOtherArticles } = useStaticQuery(graphql`
query MyQuery {
latestArticle: allContentfulBlogPost(sort: {order: DESC, fields: publishDate}, limit: 1) {
nodes {
title
slug
publishDate
excerpt {
excerpt
}
thumbnailImage {
imageFile {
id
fluid {
...GatsbyContentfulFluid
}
}
}
}
}
allOtherArticles: allContentfulBlogPost(sort: {order: DESC, fields: publishDate}, skip: 1) {
nodes {
title
slug
publishDate
}
}
}
`)
const latest = latestArticle.edges[0].node
return (
<Layout>
<ol data-sal="slide-up" data-sal-delay="300" data-sal-easing="ease" className={blogStyles.posts}>
<li className="latest-post">
<Link to={`/blog/${latest.slug}`}>
<h2>{latest.title}</h2>
<p>{latest.excerpt.excerpt}</p>
<Img fluid={latest.thumbnailImage.imageFile.fluid} />
</Link>
</li>
{allOtherArticles.edges.map((edge) => {
return (
<li className={blogStyles.post}>
<Link to={`/blog/${edge.node.slug}`}>
<h2>{edge.node.title}</h2>
<p>{edge.node.publishedDate }</p>
</Link>
</li>
)
})}
</ol>
</Layout>
)
}
export default BlogPage
The other option is to just query for all the fields you need. When you map over the data you can check the index and conditionally render the thumbnail and the excerpt (as well as the other stuff).
{data.allContentfulBlogPost.edges.map((edge, index) => {
const firstArticle = index === 0
return (
<li className={ blogStyles.post }>
<Link to={ `/blog/${edge.node.slug }`}>
{ firstArticle && (<Img fluid={edge.node.thumbnailImage.imageFile.fluid } />)}
<h2>{ edge.node.title }</h2>
{ firstArticle && (<p>{ edge.node.title }</p>)}
<p>{ edge.node.publishedDate }</p>
</Link>
</li>
)
})}
Upvotes: 1