I’m building a Gatsby site and am using the gatsby-source-contentful
plugin as well as the @contentful/rich-text-react-renderer
package to allow me to override the default html elements with React components.
Below is a very basic example of my usage, there are no overrides, and when the item is rendered everything looks fine but the embedded images are not present. They do not visibly show and are not in the DOM either.
FYI: This is TypeScript code
export const ContentfulRichText: FunctionComponent<ContentfulRichTextProps> = ({
json,
}): ReactElement => {
return <Fragment>{documentToReactComponents(json)}</Fragment>
}
Now, if I use my own components, like below, my components (or rather the ones from Theme UI) are rendered and still there are no images…
import React, { FunctionComponent, ReactElement, Fragment } from 'react'
import {
documentToReactComponents,
Options,
} from '@contentful/rich-text-react-renderer'
import { BLOCKS, INLINES } from '@contentful/rich-text-types'
import { ContentfulRichTextProps } from './ContentfulrichText.models'
import { Styled } from 'theme-ui'
import Img from 'gatsby-image'
const Hyperlink = (props): ReactElement => <Styled.a {...props} />
const options: Options = {
renderNode: {
[BLOCKS.HEADING_1]: (node, children): ReactElement => (
<Styled.h1>{children}</Styled.h1>
),
[BLOCKS.HEADING_2]: (node, children): ReactElement => (
<Styled.h2>{children}</Styled.h2>
),
[BLOCKS.HEADING_3]: (node, children): ReactElement => (
<Styled.h3>{children}</Styled.h3>
),
[BLOCKS.HEADING_4]: (node, children): ReactElement => (
<Styled.h4>{children}</Styled.h4>
),
[BLOCKS.HEADING_5]: (node, children): ReactElement => (
<Styled.h5>{children}</Styled.h5>
),
[BLOCKS.HEADING_6]: (node, children): ReactElement => (
<Styled.h6>{children}</Styled.h6>
),
[BLOCKS.PARAGRAPH]: (node, children): ReactElement => (
<Styled.p>{children}</Styled.p>
),
[BLOCKS.UL_LIST]: (node, children): ReactElement => (
<Styled.ul>{children}</Styled.ul>
),
[BLOCKS.OL_LIST]: (node, children): ReactElement => (
<Styled.ol>{children}</Styled.ol>
),
[BLOCKS.LIST_ITEM]: (node, children): ReactElement => (
<Styled.li>{children}</Styled.li>
),
[INLINES.HYPERLINK]: (node, children): ReactElement => {
return <Hyperlink href={node.data.uri}>{children}</Hyperlink>
},
},
}
export const ContentfulRichText: FunctionComponent<ContentfulRichTextProps> = ({
json,
}): ReactElement => {
return <Fragment>{documentToReactComponents(json, options)}</Fragment>
}
I can add my own image component like below, which finally renders an image, but I feel like this shouldn’t be needed. Am I wrong? I certainly shouldn’t have to set the the src
in this way, especially since I have multiple locales which would make this code very brittle.
[BLOCKS.EMBEDDED_ASSET]: (node, children): ReactElement => {
return (
<img
key={node.data.target.fields.file.en.url}
src={node.data.target.fields.file.en.url}
/>
)
},
I am also hoping to use gatsby-image
which supposedly supports Contentful but I can’t see how to set it up for rich text…
I would appreciate any pointers from someone that has done this before.
Many thanks