gatsby-paginate
gatsby-paginate copied to clipboard
Using Gatsby-Image with Gatsby-Paginate
I managed to get gatsby-paginate working, but when I include
image {
sizes(maxWidth: 400) {
...GatsbyContentfulSizes
}
}
in my graphql query in gatsby-node.js, my development build fails. I've tried to include a graphql query in my template, but I get this error: GraphQLError: Variable "$id" of required type "String!" was not provided.
Everything works when I remove the image sizes query above. Is there a way to get gatsby-image working with pagination? I've been through the examples, but haven't found one yet.
Here's the relevant gatsby-node section. Thanks.
.then(() => {
graphql(
`
{
allContentfulSongs(limit: 1000) {
edges {
node {
id
slug
title
path
image {
id
#sizes(maxWidth: 200) {
# ...GatsbyContentfulSizes
#}
}
}
}
}
}
`
).then(result => {
if (result.errors) {
reject(result.errors)
}
const categoryTemplate = path.resolve(`./src/templates/category.js`)
createPaginatedPages({
edges: result.data.allContentfulSongs.edges,
createPage: createPage,
pageTemplate: categoryTemplate,
pageLength: 5,
pathPrefix: "songs",
buildPath: (index, pathPrefix) => index > 1 ? `${pathPrefix}/${index}` : `/${pathPrefix}`
})
_.each(result.data.allContentfulSongs.edges, edge => {
createPage({
path: `${edge.node.slug}/`,
component: slash(categoryTemplate),
context: {
id: edge.node.id,
},
})
})
I'm having the same issue I guess, where [{"message":"Unknown fragment \"GatsbyContentfulSizes\".","locations":[{"line":9,"column":24}]}]
the fragment of GatsbyContentfulSizes
is not recognized properly.
I solved it by changing:
image {
sizes(maxWidth: 380) {
...GatsbyContentfulSizes
}
}
to
image {
sizes(maxWidth: 380) {
base64
aspectRatio
src
srcSet
sizes
}
}
by just looking up the contents of the fragment. Still, this is not optimal.
@aaronaustin and @danniehakan I know this is an old issue (I was just knocking around this repo)...
Anyways, GraphQL fragments like this are unavailable to queries performed in the gatsby-node
context.
The trick is to use the least amount of data in the createPage
call and move the image, and other data, retrieval to the template/component that you're passing in. (i.e. categoryTemplate
would have a Page Query that uses the data passed in from the pageContext
to get what it needs to be built.)
@elskwid could you explain that in a piece of code please?
@rsurjano What @elskwid is suggesting is to not pass more data than necessary into the template/component through context
but rather restrict yourself to identifiers that provide just enough information so that the template/component can then query for the required data itself.
A simple example would be links to the next and previous post at the end of a blog post to keep your site's visitors reading. You shouldn't query for all the data you need about the next and previous post (such as url, title, featured image, excerpt, etc.) in gatsby-node
and pass that into context
but instead just pass the post slugs or IDs which postTemplate.js
can then use to query for all required data. This is how it would look in code:
gatsby-node.js
posts.edges.forEach(({ node }, index, arr) => {
const nextSlug = index === 0 ? `` : arr[index - 1].node.frontmatter.slug
const prevSlug =
index === arr.length - 1 ? `` : arr[index + 1].node.frontmatter.slug
const slug = node.frontmatter.slug
createPage({
path: `/blog` + slug,
component: postTemplate,
context: { slug, nextSlug, prevSlug },
})
})
}
postTemplate.js
export const query = graphql`
fragment postFields on MarkdownRemark {
frontmatter {
title
slug
date(formatString: "MMM DD, YYYY")
tags
...featuredImage
}
timeToRead
excerpt(pruneLength: 200)
html
}
query($slug: String!, $prevSlug: String!, $nextSlug: String!) {
post: markdownRemark(frontmatter: { slug: { eq: $slug } }) {
...postFields
}
next: markdownRemark(frontmatter: { slug: { eq: $nextSlug } }) {
...postFields
}
prev: markdownRemark(frontmatter: { slug: { eq: $prevSlug } }) {
...postFields
}
}
`