Thank you very much for this code snippet. I don’t think this is a dirty solution as long as it is approached systematically.
I have a dynamic zone that allows the user to either input a RichText block or an Image block and the code is this:
gatsby-node
exports.onCreateNode = async ({
node,
actions: { createNode },
store,
cache,
createNodeId,
}) => {
if (node.internal.type === "StrapiPost") {
if (node.sections !== null && node.sections.length) {
let contentImages = []
for (let i = 0, len = node.sections.length; i < len; i++) {
const block = node.sections[i]
let blockImage = {}
if (block.strapi_component === "posts.image" && block.image !== null) {
let fileNode = await createRemoteFileNode({
url: `${CMS_URL}${block.image.url}`, // string that points to the URL of the image
parentNodeId: node.id, // id of the parent node of the fileNode you are going to create
createNode, // helper function in gatsby-node to generate the node
createNodeId, // helper function in gatsby-node to generate the node id
cache, // Gatsby's cache
store, // Gatsby's Redux store
})
blockImage = fileNode ? { localFile___NODE: fileNode.id } : {}
}
contentImages.push(blockImage)
}
node.sectionImages = contentImages
}
}
}
And the associated post output graphQL Query
export const query = graphql`
query Post($id: String!) {
post: strapiPost(id: { eq: $id }) {
title
excerpt
slug
featured_image {
localFile {
id
childImageSharp {
gatsbyImageData(layout: FULL_WIDTH, placeholder: NONE)
}
}
}
published_at
updated_at
categories {
id
title
slug
}
sections
sectionImages {
localFile {
id
childImageSharp {
gatsbyImageData(layout: FULL_WIDTH, placeholder: NONE)
}
}
}
}
}
`
And Components
const Post = ({ data, pageContext }) => {
const { post } = data
const { title, featured_image, categories, sections, sectionImages } = post
let imageObject = null
if (featured_image) {
imageObject = getImage(featured_image.localFile)
}
return (
<Layout>
<Grid isPost={true}>
{imageObject && (
<GatsbyImage
image={imageObject}
alt={title}
width={1072}
height={618}
/>
)}
<H2>{title}</H2>
{sections.map( (section, i) =>
RenderSection(section, sectionImages[i], i)
)}
</Grid>
</Layout>
)
}
const RenderSection = (section, sectionImage, i) => {
switch (section.strapi_component) {
case "posts.content":
return (
<div key={`section-rich-${i}`}>
<RichText content={section.content} />
</div>
)
case "posts.image":
return (
<div key={`section-image-${i}`}>
<ImageComponent data={section} image={sectionImage} index={i} />
</div>
)
}
}
const ImageComponent = ({ data, image = null, index }) => {
let imageObject = null
const { caption = false } = data
if (image) {
imageObject = getImage(image.localFile)
}
return (
<>
{imageObject && (
<GatsbyImage
image={imageObject}
alt={caption}
width={1072}
height={618}
/>
)}
{caption && (
<Xs>{caption}</Xs>
)}
</>
)
}