There are many tutorials on how to use Next.js with Contentful, but not a lot talk about how to render rich text files(RTF) with images. In this post, I'll talk about how to render RTFs with images by passing in an option to documentToReactComponents.
Problem
Here is a sample blogpost that I want to publish on my personal website.
Contentful offers documentToReactComponents function to render its rich text file fields. Install rich-text-react-renderer via npm install @contentful/rich-text-react-renderer
.
To use documentToReactComponents, first import it in your component. Then, pass in the rich text file field you fetched from Contentful using client.getEntries()
.
import {documentToReactComponents} from '@contentful/rich-text-react-renderer'
export async function getStaticProps({params}) {
const client = createClient({
space: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_KEY
})
const res = await client.getEntries({content_type: 'blogpost'})
return {
props: {
blogposts: res.items
}
}
}
In my example, I call client.getEntries()
in getStaticProps
and call documentToReactComponents
in the Blog component JSX. blogpost.fields.blogContent
is my rich text file field.
const Blog = ({blogposts}) => {
return (
<div>
<h1>Blog</h1>
{blogposts.map(blogpost => (
<div>
<h1>{blogpost.fields.title}</h1>
<div>{documentToReactComponents(blogpost.fields.blogContent)}</div>
</div>
))}
</div>
)
}
This should render some data on your app, but not all of them. In my situation, I don't see any images despite I embedded them in my RTF.
Solution
To solve this, we need to specify how to render these embedded data. We can do this by passing a second renderOption
parameter to documentToReactComponents
.
renderOption
is just an object with a renderNode key. The value associated with renderNode is an object specifying how to render the content on the RTF.
const renderOption = {
renderNode: {
[BLOCKS.EMBEDDED_ASSET]: (node, children) => {
return (<Image
src={`https:${node.data.target.fields.file.url}`}
height={node.data.target.fields.file.details.image.height}
width={node.data.target.fields.file.details.image.width}
/>)
}
}
}
The keys of renderNode
specify different types of content (like heading 1, paragraphs, or embedded assets), and the values specify the functions that transform the content to the format we want. This transformation function takes in two parameters: node and children. The node refers to the node itself while the children refers to children node of the specified content.
Helpful resources where I got all of these from
Rendering linked assets and entries in the Contentful Rich Text field by Salma Alam-Naylor
Contentful Strategies: How To Render RichText by Stefan Judis
Top comments (1)
where did you deploy your app? I am using vercel, and unfortunately when the site is built, my code options are not rendering in the same way they are locally