React renderer for the Contentful rich text field type.
npm install @contentful/rich-text-react-rendererReact renderer for the Contentful rich text field type.
Using npm:
``sh`
npm install @contentful/rich-text-react-renderer
Using yarn:
`sh`
yarn add @contentful/rich-text-react-renderer
`javascript
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
const document = {
nodeType: 'document',
data: {},
content: [
{
nodeType: 'paragraph',
data: {},
content: [
{
nodeType: 'text',
value: 'Hello world!',
marks: [],
data: {},
},
],
},
],
};
documentToReactComponents(document); // ->
Hello world!
`javascript
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';const document = {
nodeType: 'document',
content: [
{
nodeType: 'paragraph',
content: [
{
nodeType: 'text',
value: 'Hello',
marks: [{ type: 'bold' }],
},
{
nodeType: 'text',
value: ' world!',
marks: [{ type: 'italic' }],
},
],
},
],
};
documentToReactComponents(document);
// ->
Hello world!
`You can also pass custom renderers for both marks and nodes as an optional parameter like so:
`javascript
import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';const document = {
nodeType: 'document',
content: [
{
nodeType: 'paragraph',
content: [
{
nodeType: 'text',
value: 'Hello',
marks: [{ type: 'bold' }],
},
{
nodeType: 'text',
value: ' world!',
marks: [{ type: 'italic' }],
},
],
},
],
};
const Bold = ({ children }) =>
{children}
;const Text = ({ children }) =>
{children}
;const options = {
renderMark: {
[MARKS.BOLD]: (text) => {text} ,
},
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => {children} ,
},
renderText: (text) => text.replace('!', '?'),
};
documentToReactComponents(document, options);
// ->
Hello
world?
`Last, but not least, you can pass a custom rendering component for an embedded entry:
`javascript
import { BLOCKS } from '@contentful/rich-text-types';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';const document = {
nodeType: 'document',
content: [
{
nodeType: 'embedded-entry-block',
data: {
target: (...)Link<'Entry'>(...);
},
},
]
};
const CustomComponent = ({ title, description }) => (
{title}
{description}
);const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: (node) => {
const { title, description } = node.data.target.fields;
return
}
}
};
documentToReactComponents(document, options);
// ->
[title]
[description]
`The
renderNode keys should be one of the following BLOCKS and INLINES properties as defined in @contentful/rich-text-types:-
BLOCKS
- DOCUMENT
- PARAGRAPH
- HEADING_1
- HEADING_2
- HEADING_3
- HEADING_4
- HEADING_5
- HEADING_6
- UL_LIST
- OL_LIST
- LIST_ITEM
- QUOTE
- HR
- EMBEDDED_ENTRY
- EMBEDDED_ASSET
- EMBEDDED_RESOURCE-
INLINES
- EMBEDDED_ENTRY (this is different from the BLOCKS.EMBEDDED_ENTRY)
- EMBEDDED_RESOURCE
- HYPERLINK
- ENTRY_HYPERLINK
- ASSET_HYPERLINK
- RESOURCE_HYPERLINKThe
renderMark keys should be one of the following MARKS properties as defined in @contentful/rich-text-types:-
BOLD
- ITALIC
- UNDERLINE
- CODEThe
renderText callback is a function that has a single string argument and returns a React node. Each text node is evaluated individually by this callback. A possible use case for this is to replace instances of \n produced by Shift + Enter with React elements. This could be accomplished in the following way:`javascript
const options = {
renderText: (text) => {
return text.split('\n').reduce((children, textSegment, index) => {
return [...children, index > 0 &&
, textSegment];
}, []);
},
};
`#### Note on adding a
key prop in custom renderers:It is possible to pass a
key prop in the components returned by custom renderers. A good use case for this is in embeded entries using the node's target.sys.id. It is important not to pass anything that is index-like (e.g. 1 or "1") as it may clash with the default renderers which automatically inject a key prop using their index in the Contentful rich text AST.To work around this limitation, just append any non-numeric character to your custom key.
`javascript
const options = {
renderMark: {
[MARKS.BOLD]: (text) => {
return ${text}-key}>{text};
},
},
};
`#### Preserving Whitespace
The
options object can include a preserveWhitespace boolean flag. When set to true, this flag ensures that multiple spaces in the rich text content are preserved by replacing them with , and line breaks are maintained with tags. This is useful for content that relies on specific formatting using spaces and line breaks.Note that
preserveWhitespace is not compatible with the renderText option. When the functionality of preserveWhitespace is desired along with a custom renderText callback, it should be implemented within the callback instead.`javascript
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';const document = {
nodeType: 'document',
content: [
{
nodeType: 'paragraph',
content: [
{
nodeType: 'text',
value: 'Hello world!',
marks: [],
},
],
},
],
};
const options = {
preserveWhitespace: true,
};
documentToReactComponents(document, options);
// ->
Hello world!
``In this example, the multiple spaces between "Hello" and "world!" are preserved in the rendered output.