# @contentful/rich-text-react-renderer

> React renderer for the Contentful rich text field type.

Latest version **16.2.2** (published 2026-07-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install @contentful/rich-text-react-renderer
pnpm add @contentful/rich-text-react-renderer
yarn add @contentful/rich-text-react-renderer
bun add @contentful/rich-text-react-renderer
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 16.2.2 |
| Published | 2026-07-23 |
| First published | 2019-02-11 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20.0.0 |
| Dependencies | 1 |
| Unpacked size | 148 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | it-internal, whydah-gally, contentful-ecosystem, michaelpearce |

## Links

- npm: https://www.npmjs.com/package/@contentful/rich-text-react-renderer
- Repository: https://github.com/contentful/rich-text
- Homepage: https://github.com/contentful/rich-text#readme
- Issues: https://github.com/contentful/rich-text/issues
- npm.io page: https://npm.io/package/@contentful/rich-text-react-renderer

## Dependencies (1)

- [@contentful/rich-text-types](https://npm.io/package/@contentful/rich-text-types.md) ^17.2.7

## Recent versions

- 16.2.2 (latest) — 2026-07-23
- 16.2.1 — 2026-04-09
- 16.2.0 — 2026-04-08
- 16.1.6 — 2025-11-04
- 16.1.5 — 2025-09-23
- 16.1.4 — 2025-09-23
- 16.1.3 — 2025-09-10
- 16.1.2 — 2025-09-09
- 16.1.1 — 2025-09-05
- 16.1.0 — 2025-07-15
- 16.0.2 — 2025-06-16
- 16.0.1 — 2024-12-11
- 16.0.0 — 2024-10-29
- 15.22.11 — 2024-09-09
- 15.22.10 — 2024-08-26
- … 62 more at https://npm.io/package/@contentful/rich-text-react-renderer/versions

## README

# rich-text-react-renderer

React renderer for the Contentful rich text field type.

## Installation

Using [npm](http://npmjs.org/):

```sh
npm install @contentful/rich-text-react-renderer
```

Using [yarn](https://yarnpkg.com/):

```sh
yarn add @contentful/rich-text-react-renderer
```

## Usage

```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); // -> <p>Hello world!</p>
```

```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);
// -> <p><b>Hello</b><u> world!</u></p>
```

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 }) => <p className="bold">{children}</p>;

const Text = ({ children }) => <p className="align-center">{children}</p>;

const options = {
  renderMark: {
    [MARKS.BOLD]: (text) => <Bold>{text}</Bold>,
  },
  renderNode: {
    [BLOCKS.PARAGRAPH]: (node, children) => <Text>{children}</Text>,
  },
  renderText: (text) => text.replace('!', '?'),
};

documentToReactComponents(document, options);
// -> <p class="align-center"><p class="bold">Hello</p><u> world?</u></p>
```

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 }) => (
  <div>
    <h2>{title}</h2>
    <p>{description}</p>
  </div>
);

const options = {
  renderNode: {
    [BLOCKS.EMBEDDED_ENTRY]: (node) => {
      const { title, description } = node.data.target.fields;
      return <CustomComponent title={title} description={description} />
    }
  }
};

documentToReactComponents(document, options);
// -> <div><h2>[title]</h2><p>[description]</p></div>
```

The `renderNode` keys should be one of the following `BLOCKS` and `INLINES` properties as defined in [`@contentful/rich-text-types`](https://www.npmjs.com/package/@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_HYPERLINK`

The `renderMark` keys should be one of the following `MARKS` properties as defined in [`@contentful/rich-text-types`](https://www.npmjs.com/package/@contentful/rich-text-types):

- `BOLD`
- `ITALIC`
- `UNDERLINE`
- `CODE`

The `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 `<br/>` 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 && <br key={index} />, 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 <b key={`${text}-key`}>{text}</b>;
    },
  },
};
```

#### 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 `&nbsp;`, and line breaks are maintained with `<br />` 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);
// -> <p>Hello&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;world!</p>
```

In this example, the multiple spaces between "Hello" and "world!" are preserved in the rendered output.

---
_Source: https://npm.io/package/@contentful/rich-text-react-renderer · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
