We're bringing in some posts from a Wordpress backend, some have pictures (in an ACF field) and some don't. The problem is that Gatsby infers the schema based off of the first node it receives. If it receives a node without a picture, then the schema is wrong.
Where does Gatsby’s GraphQL schema come from? With Gatsby, we use plugins which fetch data from different sources. We then use that data to automatically infer a GraphQL schema.
How can we dictate a schema to GraphQL/Gatsby that always includes a picture, with 'null' as the default value if it's blank?
{
allWordpressWpTestimonial {
edges {
node {
id
title
acf {
photo_fields {
photo {
id
localFile {
childImageSharp {
sizes {
src
}
}
}
}
}
}
}
}
}
}
In the example above, sometimes 'photo' doesn't exist and it breaks everything...
Gatsby config:
const innertext = require('innertext')
const url = require('url')
module.exports = {
siteMetadata: {
title: 'Test',
googleMapsAPIKey: 'xxxxxx',
adminBaseUrl: '123.123.123',
adminProtocol: 'http',
},
pathPrefix: '/web/beta',
plugins: [
'gatsby-plugin-react-next',
'gatsby-plugin-react-helmet',
'gatsby-plugin-sharp',
'gatsby-plugin-svgr',
{
resolve: 'gatsby-plugin-google-analytics',
options: {
trackingId: 'GOOGLE_ANALYTICS_TRACKING_ID',
},
},
{
resolve: 'gatsby-plugin-bugherd',
options: {
key: 'xxxxxx',
showInProduction: true,
},
},
{
resolve: '@andrew-codes/gatsby-plugin-elasticlunr-search',
options: {
fields: ['title', 'url', 'textContent', 'urlSearchable'],
resolvers: {
wordpress__PAGE: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => url.parse(node.link).path,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
wordpress__POST: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => `/news/${node.slug}`,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
wordpress__wp_industry: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => `/business/industries/${node.slug}`,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
},
},
},
{
resolve: 'gatsby-source-wordpress',
options: {
baseUrl: 'xxxxxx',
protocol: 'http',
hostingWPCOM: false,
useACF: true,
auth: {
htaccess_user: 'admin',
htaccess_pass: 'xxxxxx',
htaccess_sendImmediately: false,
},
verboseOutput: false,
},
},
'gatsby-transformer-sharp',
],
}
It's been awhile since this post, but since version 2.2 Gatsby has added a new API that'll make it much easier to customize schema. This is not an example with wordpress but with gatsby's gatsby-transformer-remark
, but I'm sure it's applicable.
I have a bunch of .md
with frontmatter looks like this:
---
title: "Screen title"
image: "./hero-image.png" <--- sometimes it's an empty string, ""
category: "Cat"
---
...content...
If Gatsby get to the .md
with the empty image first, it'll incorrectly infer that field as String
, even though it should be File
. With the new API, I can tell Gatsby about image field in gatsby-node.js
:
exports.sourceNodes = ({ actions, schema }) => {
const { createTypes } = actions
createTypes(`
type MarkdownRemarkFrontmatter {
image: File
}
type MarkdownRemark implements Node {
frontmatter: MarkdownRemarkFrontmatter
}
`)
}
This'll guarantee the image
field to always be of File type, otherwise it'll be null
.
Some notes:
MarkdownRemark
has to implement Node
MarkdownRemarkFrontmatter
type, then pass it to the frontmatter
field in MarkdownRemark
node.category
field in MarkdownRemarkFrontmatter
, it will be inferred by Gatsby just like before.MarkdownRemark
, MarkdownRemarkFrontmatter
) is to look for them in graphiql (default at localhost:8000/___graphql
)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With