npm package: @os-team/draft-to-react-nodes
Description: Converts the Draft.js state (RawDraftContentState) to ReactNode.
Latest version: 1.2.2

# @os-team/draft-to-react-nodes [![NPM version](https://img.shields.io/npm/v/@os-team/draft-to-react-nodes)](https://yarnpkg.com/package/@os-team/draft-to-react-nodes) [![BundlePhobia](https://img.shields.io/bundlephobia/minzip/@os-team/draft-to-react-nodes)](https://bundlephobia.com/result?p=@os-team/draft-to-react-nodes)

Converts the Draft.js state (RawDraftContentState) to ReactNode.

Draft.js allows to convert the state to a raw JS structure (RawDraftContentState) using [convertToRaw](https://draftjs.org/docs/api-reference-data-conversion/#converttoraw).
This function is used before saving the Draft.js editor state to the database.
When a frontend written in React receives this state, it must be converted to ReactNode.
This library do it.

## Usage

Install the package using the following command:

```
yarn add @os-team/draft-to-react-nodes
```

### Simple usage

Import the `draftToReactNodes` function and pass RawDraftContentState to `value`.

```tsx
import React from 'react';
import draftToReactNodes from '@os-team/draft-to-react-nodes';

interface PostProps {
  title: string;
  content: any;
}

const Post: React.FC<PostProps> = ({ title, content }) => (
  <>
    <h1>{title}</h1>
    {draftToReactNodes({ value: content })}
  </>
);

export default Post;
```

### Advanced usage

You can define how to render any blocks, entities, and inline styles using `blockRenderer`, `entityRenderer`, and `inlineStyleRenderer` respectively.

```tsx
import React from 'react';
import draftToReactNodes from '@os-team/draft-to-react-nodes';
import { Link } from 'react-router';

interface PostProps {
  title: string;
  content: any;
}

const contentToReactNode = (value: any) =>
  draftToReactNodes({
    value,
    blockRenderer: (block, children) => {
      // Render paragraphs as div
      if (block.type === 'paragraph') {
        return <div key={block.key}>{children}</div>;
      }
      // Render images
      if (block.type === 'atomic:image') {
        return <img key={block.key} src={block.data.src} alt={block.text} />;
      }
      return null;
    },
    entityRenderer: (entity) => {
      // Render links
      if (
        entity.type === 'LINK' &&
        entity.data &&
        typeof entity.data.url === 'string'
      ) {
        return (
          <a key={entity.key} href={entity.data.url}>
            {entity.text}
          </a>
        );
      }
      return null;
    },
    inlineStyleRenderer: (inlineStyle) => {
      // Render bold elements as span with the `bold` class name
      if (inlineStyle.style === 'BOLD') {
        return (
          <span key={inlineStyle.key} className='bold'>
            {inlineStyle.text}
          </span>
        );
      }
      // Render custom inline style elements
      if (inlineStyle.style === 'CUSTOM') {
        return (
          <span key={inlineStyle.key} className='custom'>
            {inlineStyle.text}
          </span>
        );
      }
      return null;
    },
  });

const Post: React.FC<PostProps> = ({ title, content }) => (
  <>
    <h1>{title}</h1>
    {contentToReactNode(content)}
  </>
);

export default Post;
```