I'm running into an issue where I've created a non page component with a StaticQuery that is pulling information with a set up like this.
const BestSellers = () => (
<div>
<StaticQuery
query={bestSellerQuery}
render={data => (
<div>
{data.allMarkdownRemark.edges.map(({ node }) => (
<Card className="m-2 index-card" key={node.id}>
<Link to={node.fields.slug}>
<GatsbyImage
className="card-img-top"
image={node.frontmatter.image}
alt={node.frontmatter.description}
/>
</Link>
<hr />
<CardBody>
<Link to={node.fields.slug}>
<CardTitle className="h4 text-light text-wrap">
{node.frontmatter.title}
</CardTitle>
</Link>
<CardSubtitle>{node.frontmatter.description}</CardSubtitle>
{/* <CardSubtitle>{node.excerpt}</CardSubtitle> */}
<CardSubtitle className="float-left mt-5">
Price: ${node.frontmatter.price}
</CardSubtitle>
<CardSubtitle>
<Badge color="danger float-right mt-5">
{node.frontmatter.tag}
</Badge>
</CardSubtitle>
</CardBody>
</Card>
))}
</div>
)}
/>
</div>
);
const bestSellerQuery = graphql`
query bestSellerQuery {
allMarkdownRemark(
filter: { frontmatter: { tag: { eq: "popular" }}}
sort: { fields: [frontmatter___date], order: DESC }
limit: 2
) {
edges {
node {
id
frontmatter {
title
description
price
tag
image {
childImageSharp {
gatsbyImageData(
layout: CONSTRAINED
height: 600
placeholder: BLURRED
formats: [AUTO, JPG]
transformOptions: { fit: COVER, cropFocus: ATTENTION }
)
}
}
}
fields {
slug
}
excerpt
}
}
}
}
`
export default BestSellers;
What I'm doing is my pages are being created programmatically from a Markdown file once it is clicked on so I'm trying to import this into the template that i use to create pages and it just shows loading(static query) I've tried using this same query in pages that do and don't have a page query on them and it results in the same as using this in the template component that I'm trying to use it in.
It was the issues in the graphql query which was being used more specifically the line
filter: { frontmatter: { tag: { eq: "popular" }}}
the issue was the "popular" in the MD file is in caps so by changing it to "POPULAR" that solved it....
Related
I'm pretty new here to gatsby/programming and i was playing around with the gatsby. I have below issue and I would appreciate if you could let me know where does it goes wrong? Below is my code.
Problem 1: Why i can't return/access the {post1.categories.nodes.name} ? It shows nothing on my page.
Note that there was no problem for me to access {post.video.videoSource} so i guess my Graphql worked fine but when i tried with {post1.categories.nodes.name}, it was literally blank.
Any suggestions? Thank you very much.
const BlogIndex = ({
data,
pageContext: { nextPagePath, previousPagePath },
}) => {
const posts = data.allWpPost.nodes
if (!posts.length) {
return (
<Layout isHomePage>
<Seo title="All posts" />
<Bio />
<p>
No blog posts found. Add posts to your WordPress site and they'll
appear here!
</p>
</Layout>
)
}
return (
<Layout isHomePage>
<Seo title="All posts" />
{/* <Bio /> */}
<Grid container rowSpacing={5} column spacing={5}>
<Grid item xs={12} sm={3} md={3} lg={3}>
<Paper>
<ol style={{ listStyle: `none` }}>
{posts.map(post1 => {
return <li>{post1.categories.nodes.name}</li>
})}
</ol>
</Paper>
</Grid>
<Grid item xs={12} sm={9} md={9} lg={9}>
<Paper>
<ol style={{ listStyle: `none` }}>
{posts.map(post => {
const hasVideoUrl = post.video.videoSource
if (hasVideoUrl !== null) {
return (
<li key={post.uri}>
<article
className="post-list-item"
itemScope
itemType="http://schema.org/Article"
>
<header>
<small>{post.video.videoSource}</small>
<small>{post.video.videoUrl}</small>
{/* <ReactPlayer url={post.video.videoUrl} /> */}
</header>
</article>
</li>
)
} else {
return null
}
})}
</ol>
</Paper>
</Grid>
</Grid>
{previousPagePath && (
<>
<Link to={previousPagePath}>Previous page</Link>
<br />
</>
)}
{nextPagePath && <Link to={nextPagePath}>Next page</Link>}
</Layout>
)
}
export default BlogIndex
export const pageQuery = graphql`
query WordPressPostArchive($offset: Int!, $postsPerPage: Int!) {
allWpPost(
sort: { fields: [date], order: DESC }
limit: $postsPerPage
skip: $offset
) {
nodes {
excerpt
uri
date(formatString: "MMMM DD, YYYY")
title
video {
videoSource
videoUrl
}
categories {
nodes {
name
}
}
}
}
}
`
Problem 2 [Added 2 July 2022]:
<ul>
{wpPosts.map(wpPost => {
wpPost.tags.nodes.map(tag => {
console.log(tag.name)
if (tag.name === "Blog") {
return (
<div>
<li>{tag.title}</li>
</div>
)
}
})
})}
</ul>
const data = useStaticQuery(
graphql`
query {
allWpPost(sort: { fields: date, order: DESC }, limit: 10) {
nodes {
excerpt
slug
uri
video {
videoTitle
videoUrl
}
title
date(formatString: "MMMM DD, YYYY")
tags {
nodes {
name
}
}
}
}
}
`
)
const wpPosts = data.allWpPost.nodes
Problem 1: Why i can't return/access the {post1.categories.nodes.name}
? It shows nothing on my page.
nodes (in post1.categories.nodes.name) is likely to be an array, so you will need to loop through it or access a specific position:
return <li>{post1.categories.nodes[0].name}</li>
Depending on your data structure you'll need to loop or just access to the first position. Without knowing your data it's difficult to guess.
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
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>
)
})}
I'm building my website with GatsbyJS and graphsql. On my projects site I want to display a grid with Images that Link to further sites.
In order to do that I need to query multiple images. I created a folder in my images folder called "portfolio" and I want to query all the pictures in there.
I have used useStaticQuery before but I've read that currently it's only possible to query one instance so I tried doing it like this, but the code is not working. Any help? Thanks a lot!
import React from 'react'
import Img from 'gatsby-image'
import { graphql } from 'gatsby'
const Portfolio = ({data}) => (
<>
{data.allFile.edges.map(image => {
return (
<div className="sec">
<div className="portfolio">
<div className="containerp">
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>
</div>
</div>
</div>
) })}
</>
)
export default Portfolio
export const portfolioQuery = graphql`
{
allFile(filter: {relativeDirectory: {eq: "portfolio"}}) {
edges {
node {
id
childImageSharp {
fluid(maxWidth: 500) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`;
Is it possible that you have some images missing, so none are rendering?
You could try checking that the image is present before rendering the Img, like this:
{image.node.childImageSharp &&
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>}
NB:
If you like, you could also make it a bit clearer by assigning your mapping object (edges) to a variable. It doesn't make that much difference in this example but can be clearer if you have more going on in your component.
E.g.
const Portfolio = ({data}) => (
<>
const images = data.allFile.edges
{images.map(image => {
return (
<div className="sec">
<div className="portfolio">
<div className="containerp">
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>
</div>
</div>
</div>
) })}
</>
)
It's most likely that you probably need to set up your 'gatsby-source-filesystem' to recognize images within a query.
in your gatsby-config.js:
{
resolve: gatsby-source-filesystem,
options: {
name: images,
path: ./src/images/,
},
},
I decided to create a small project in new technology and I choose Gatsby. To let you know I don't work with React and GraphQl before. So thanks to Gatsby I can see also other technologies. So, for now, I try to make an index survey page where the footer and header are modifiable. I take for my backend Contentful and I succeed to do the connection between the content from ContentFul and my component footer. But when I try to do a query in the page index.js impossible to get the data, but they exist (I checked on graphql).
I try to make the query in the component, make the query in a hook and then call the hook. But nothing changes always undefined
In my index.js:
const query = graphql`
query header{
contentfulHeader {
id
titleCard
descriptionCard
logoCard {
file {
url
}
}
}
}
`
const SurveyTitleCard = props => {
return (
<>
<div className="row">
<div className="survey-title card blue-grey darken-3 col s10 offset-s1 m6 offset-m3">
<div className="card-content grey-text text-lighten-3 center-align">
<div className="row logo valign-wrapper">
<div className="col s6 offset-s3 m4 offset-m4">
<img
className="responsive-img"
src=""
alt="logo company"
/>
</div>
</div>
<div className="card-title">
{query.contentfulHeader.titleCard}
</div>
<p>We would love to hear your anonymous thoughts and feedback</p>
</div>
</div>
</div>
</>
)
}
// INDEX PAGE
const IndexPage = () => (
<Layout>
<SEO title="Home" />
<SurveyTitleCard />
</Layout>
)
Here the data from GraphQl:
Here my gatsby-config.js:
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `#AntoineB`,
},
plugins: [
{
resolve: `gatsby-source-contentful`,
options:{
spaceId: `MY_SPACE_ID`,
accessToken: `MY_ACCESS_TOKEN`,
},
},
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
],
}
See the docs regarding querying data in components using StaticQuery
import React from "react"
import { StaticQuery, graphql } from "gatsby"
export default () => (
<StaticQuery
query={graphql`
query header{
contentfulHeader {
id
titleCard
descriptionCard
logoCard {
file {
url
}
}
}
}
`}
render={data => (
<>
<div className="row">
<div className="survey-title card blue-grey darken-3 col s10 offset-s1 m6 offset-m3">
<div className="card-content grey-text text-lighten-3 center-align">
<div className="row logo valign-wrapper">
<div className="col s6 offset-s3 m4 offset-m4">
<img
className="responsive-img"
src=""
alt="logo company"
/>
</div>
</div>
<div className="card-title">
{data.contentfulHeader.titleCard}
</div>
<p>We would love to hear your anonymous thoughts and feedback</p>
</div>
</div>
</div>
</>
)}
/>
)
GOAL: use Gatsby to render Drupal 8 images associated with nodes
I can render the default Drupal 8 Article node info just fine using a GraphQL query. I cannot get the default image field to render (field_image) - it just renders the url of the image. So I'm almost there but definitely missing something fundamental. Help please?
import React from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
const BlogPage = ({data}) => (
<div>
<h1>Know What Grinds My Gears?</h1>
{ data.allNodeArticle.edges.map(
(
{ node }) => (
<div>
#the next Img line doesn't work (renders nothing)
<Img fluid={ node.relationships.field_image.uri.url } />
<h3> { node.title } </h3>
<div dangerouslySetInnerHTML={{ __html: node.body.summary }} />
<Link to= { node.id } >read</Link>
#the next <figure> line doesn't work (renders correct url to image file)
<figure> { node.relationships.field_image.uri.url }</figure>
</div>
)
)
}
</div>
)
export default BlogPage
export const query = graphql`
query allNodeArticle {
allNodeArticle {
edges {
node {
id
title
body {
value
format
processed
summary
}
relationships {
field_image {
uri {
value
url
}
}
}
}
}
}
}
`
what am I doing wrong?
The way we manage this is by having on the GraphQL of the node image:
field_image {
relationships {
field_media_image {
localFile {
publicURL
childImageSharp {
fluid(maxWidth: 520 maxHeight: 520, cropFocus: CENTER) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
And then using it as
<Img
fluid={
data.nodePage.relationships.field_image.relationships.field_media_image.localFile.childImageSharp.fluid
}
/>