Using documentToReactComponents with options
Tags: nextjs, contentful, javascript, react
Published: 2021-05-11 03:34:11

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.
![Screen Shot 2021-05-10 at 10.46.07 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqm05q51x42veee4obt8.png)
 
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.
![Screen Shot 2021-05-10 at 10.58.02 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6bybua10ypopyls7qj34.png)

## 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.


&nbsp;
&nbsp;
Helpful resources where I got all of these from
    
    
-  [**Rendering linked assets and entries in the Contentful Rich Text field**](https://www.contentful.com/blog/2021/04/14/rendering-linked-assets-entries-in-contentful/) by Salma Alam-Naylor

- [**Contentful Strategies: How To Render RichText**](https://www.youtube.com/watch?v=MSbpKwZMaXQ) by Stefan Judis