LAST EDIT: fixed. It was a naming convention. I am currently using this tree structure:
-pages
--posts
---00X-post
For pagination/programmatically works fine so far. And inside, md with its correspondent image (used as a thumbnail too). One of those had the naming wrong. Fixed. Now everything is working just fine.
EDIT and UPDATE:
Thank you for your quick answer. I tried that, nothing changed. I do believe it has to do with all the templates for pagination I am currently using. For example, the one in charge of creating page 2 and so in is this one:
import React from 'react';
import Layout from '../components/layout';
import Post from '../components/Post';
import { graphql } from 'gatsby';
import { Row, Col } from 'reactstrap';
import Sidebar from '../components/Sidebar';
import PaginationLinks from '../components/PaginationLinks';
const postList = (props) => {
const posts = props.data.allMarkdownRemark.edges
const { currentPage, numberOfPages } = props.pageContext
return (
<Layout pageTitle>
<h1 className='titles'>{`page ${currentPage}`}</h1>
<Row>
<Col>
{posts.map(({node}) => (
<Post
key={node.id}
slug={node.fields.slug}
title={node.frontmatter.title}
author={node.frontmatter.author}
date={node.frontmatter.date}
body={node.excerpt}
tags={node.frontmatter.tags}
fluid={node.frontmatter.image.childImageSharp.fluid}
/>
))}
<PaginationLinks
currentPage={currentPage}
numberOfPages={numberOfPages}
/>
</Col>
<Col md='4'>
<Sidebar>
</Sidebar>
</Col>
</Row>
</Layout>
)
}
export const postListQuery = graphql`
query postListQuery($skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC}
limit: $limit
skip: $skip
) {
edges {
node {
id
frontmatter {
title
date
author
tags
image {
childImageSharp {
fluid(maxWidth: 650, quality: 90) {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
excerpt
}
}
}
}
`
export default postList
Same error messages appear when creating pages by tags/authors. If I delete the image field from the query, everything works. This is unusual.
While doing a simple blog project with Gatsby I run into either "TypeError: childImageSharp is undefined” or "node.frontmatter.image is null". This error message appears at random. By the time I started writing this, trying to access pages/2 only triggered it.
Here's index.js:
import React from "react"
import { graphql, StaticQuery } from 'gatsby';
import Layout from "../components/layout"
import SEO from "../components/seo"
import Post from '../components/Post';
import Sidebar from '../components/Sidebar';
import { Row, Col } from 'reactstrap';
import PaginationLinks from '../components/PaginationLinks';
const IndexPage = () => {
const postsPerPage = 5;
let numberOfPages
return (
<Layout>
<SEO title="home" keywords={[`procedural`, `gatsby`]}/>
<h1 className='titles'>procedural</h1>
<Row>
<Col>
<StaticQuery
query={indexQuery}
render={data => {
numberOfPages = Math.ceil(
data.allMarkdownRemark.totalCount / postsPerPage
);
return (
<div>
{
data.allMarkdownRemark.edges.map(({ node }) => (
<Post
key={node.id}
title={node.frontmatter.title}
author={node.frontmatter.author}
date={node.frontmatter.date}
slug={node.fields.slug}
body={node.excerpt}
fluid={node.frontmatter.image.childImageSharp.fluid}
tags={node.frontmatter.tags}
/>
))
}
<PaginationLinks currentPage={1} numberOfPages={numberOfPages} />
</div>
)
}}
/>
</Col>
<Col md='4'>
<Sidebar>
</Sidebar>
</Col>
</Row>
</Layout>
)
}
const indexQuery = graphql`
query {
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC}
limit: 5
) {
totalCount
edges {
node {
id
frontmatter {
title
date
author
tags
image {
childImageSharp {
fluid(quality: 85, maxWidth: 960) {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
excerpt
}
}
}
}
`
export default IndexPage
Here's gatsby-node.js:
const path = require('path');
const { slugify } = require('./src/utils/utilityFunctions');
const authors = require('./src/utils/authors');
const _ = require('lodash');
// single post generator
exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions
if(node.internal.type === 'MarkdownRemark') {
const slugFromTitle = slugify(node.frontmatter.title)
createNodeField({
node,
name: 'slug',
value: slugFromTitle,
})
}
}
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions;
const templates = {
singlePost: path.resolve('./src/templates/single-post.js'),
tagsPage: path.resolve('./src/templates/tags-page.js'),
tagPosts: path.resolve('./src/templates/tag-post.js'),
postList: path.resolve('./src/templates/post-list.js'),
authorPosts: path.resolve('./src/templates/author-posts.js'),
}
const res = await graphql(`
{
allMarkdownRemark {
edges {
node {
frontmatter{
author
tags
}
fields {
slug
}
}
}
}
}
`)
if(res.errors) return Promise.reject(res.errors)
const posts = res.data.allMarkdownRemark.edges
posts.forEach(({node}) => {
createPage({
path: node.fields.slug,
component: templates.singlePost,
context: {
// passing slug, PENDING TAGS
slug: node.fields.slug,
// finding author imageUrl from authors.js and passing it to the single post template
},
})
})
// creating post pages
const postsPerPage = 5
const numberOfPages = Math.ceil(posts.length / postsPerPage)
Array.from({ length: numberOfPages }).forEach((_, index) => {
const isFirstPage = index === 0
const currentPage = index + 1
// skip first page and go to index.js
if (isFirstPage) return
createPage({
path: `/page/${currentPage}`,
component: templates.postList,
context: {
limit: postsPerPage,
skip: index * postsPerPage,
numberOfPages: numberOfPages,
currentPage: currentPage,
},
})
})
// tags PAGE GENERATOR; getting all tags
let tags = []
_.each(posts, edge => {
if (_.get(edge, 'node.frontmatter.tags')) {
tags = tags.concat(edge.node.frontmatter.tags)
}
})
// account of tags, we're putting them like this: ['design', 'example', 'luck'] and also {design: X, example: Y, luck: z}
let tagPostCounts = {}
tags.forEach(tag => {
tagPostCounts[tag] = (tagPostCounts[tag] || 0) + 1;
})
tags = _.uniq(tags) //elimninate all duplicate entries
// create tags page here
createPage({
path: `/tags`,
component: templates.tagsPage,
context: {
tags,
tagPostCounts,
}
})
// tag post page creation here:
tags.forEach(tag => {
createPage({
path: `/tag/${_.kebabCase(tag)}`,
component: templates.tagPosts,
context: {
tag
}
})
})
// CREATING PAGES FOR EACH AUTHOR'S POSTS:
authors.forEach(author => {
createPage({
path: `/author/${slugify(author.name)}`,
component: templates.authorPosts,
context: {
authorName: author.name,
imageUrl: author.imageUrl,
},
})
})
}
here's gatsby-config.js:
plugins: [
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
`gatsby-plugin-react-helmet`,
`gatsby-plugin-sass`,
`gatsby-transformer-remark`,
`gatsby-plugin-catch-links`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/pages`,
},
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `procedural`,
short_name: `procedural`,
start_url: `/`,
background_color: `#663399`, // PLACEHOLDER
theme_color: `#663399`, // PLACEHOLDER
display: `minimal-ui`, // PLACEHOLDER
icon: `src/images/logo.png`, // This path is relative to the root of the site.
},
},
],
And here's my single-post.js:
import React from 'react';
import Layout from '../components/layout';
import { graphql, Link } from 'gatsby';
import SEO from '../components/seo';
import { Badge, Card, CardBody, CardSubtitle } from 'reactstrap';
import Img from 'gatsby-image';
import { slugify } from '../utils/utilityFunctions';
const SinglePost = ({ data, pageContext }) => {
const post = data.markdownRemark.frontmatter;
return (
<Layout>
<SEO title={post.title}/>
<h1 className='postTitles'>{post.