What is html-to-react?
The html-to-react npm package is a utility that allows you to convert raw HTML strings into React components. This can be particularly useful for rendering HTML content dynamically in a React application.
What are html-to-react's main functionalities?
Basic HTML to React Conversion
This feature allows you to convert a simple HTML string into a React element. The `HtmlToReact.Parser` class is used to parse the HTML string and convert it into a React component.
const HtmlToReact = require('html-to-react');
const htmlToReactParser = new HtmlToReact.Parser();
const html = '<div>Hello, <strong>world</strong>!</div>';
const reactElement = htmlToReactParser.parse(html);
Custom Processing Instructions
This feature allows you to define custom processing instructions to handle specific HTML tags in a custom way. In this example, all `div` elements are given a custom class name.
const HtmlToReact = require('html-to-react');
const htmlToReactParser = new HtmlToReact.Parser();
const processingInstructions = [
{
shouldProcessNode: function (node) {
return node.name && node.name === 'div';
},
processNode: function (node, children, index) {
return React.createElement('div', { key: index, className: 'custom-div' }, children);
}
}
];
const html = '<div>Hello, <strong>world</strong>!</div>';
const reactElement = htmlToReactParser.parseWithInstructions(html, () => true, processingInstructions);
Handling Complex HTML Structures
This feature demonstrates the ability to handle more complex HTML structures, such as nested elements. The parser can convert nested HTML elements into nested React components.
const HtmlToReact = require('html-to-react');
const htmlToReactParser = new HtmlToReact.Parser();
const html = '<div><p>Paragraph 1</p><p>Paragraph 2</p></div>';
const reactElement = htmlToReactParser.parse(html);
Other packages similar to html-to-react
react-html-parser
The react-html-parser package is another utility for converting HTML strings into React components. It offers similar functionality to html-to-react but with a simpler API. It is particularly useful for straightforward HTML to React conversions without the need for custom processing instructions.
html-react-parser
The html-react-parser package is a highly performant library for converting HTML strings into React components. It supports custom processing instructions and is known for its speed and efficiency. It is a good alternative to html-to-react for performance-critical applications.
react-dom-parser
The react-dom-parser package allows you to parse HTML strings and convert them into React elements. It provides a flexible API for handling various HTML structures and is comparable to html-to-react in terms of functionality and ease of use.
html-to-react
A lightweight library that converts raw HTML to a React DOM structure.
Why?
I had a scenario where an HTML template was generated by a different team, yet I wanted to leverage
React for the parts I did have control over. The template basically contains something like:
<div class="row">
<div class="col-sm-6">
<div data-report-id="report-1">
<!-- A React component for report-1 -->
</div>
</div>
<div class="col-sm-6">
<div data-report-id="report-2">
<!-- A React component for report-2 -->
</div>
</div>
</div>
I had to replace each <div>
that contains a data-report-id
attribute with an actual report,
which was nothing more than a React component.
Simply replacing the <div>
elements with a React component would end up with multiple top-level
React components that have no common parent.
The html-to-react module solves this problem by parsing each DOM element and converting it to a
React tree with one single parent.
Installation
$ npm install --save html-to-react
Examples
Simple
The following example parses each node and its attributes and returns a tree of React elements.
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
var htmlInput = '<div><h1>Title</h1><p>A paragraph</p></div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
assert.equal(reactHtml, htmlInput);
With Custom Processing Instructions
If certain DOM nodes require specific processing, for example if you want to capitalize each
<h1>
tag, the following example demonstrates this:
var ReactDOMServer = require('react-dom/server');
var HtmlToReact = require('html-to-react');
var HtmlToReactParser = require('html-to-react').Parser;
var htmlInput = '<div><h1>Title</h1><p>Paragraph</p><h1>Another title</h1></div>';
var htmlExpected = '<div><h1>TITLE</h1><p>Paragraph</p><h1>ANOTHER TITLE</h1></div>';
var isValidNode = function () {
return true;
};
var processNodeDefinitions = new HtmlToReact.ProcessNodeDefinitions(React);
var processingInstructions = [
{
shouldProcessNode: function (node) {
return node.parent && node.parent.name && node.parent.name === 'h1';
},
processNode: function (node, children) {
return node.data.toUpperCase();
}
}, {
shouldProcessNode: function (node) {
return true;
},
processNode: processNodeDefinitions.processDefaultNode
}];
var htmlToReactParser = new HtmlToReactParser();
var reactComponent = htmlToReactParser.parseWithInstructions(htmlInput, isValidNode,
processingInstructions);
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactComponent);
assert.equal(reactHtml, htmlExpected);
Replace the Children of an Element
There may be a situation where you want to replace the children of an element with a React
component. This is beneficial if you want to:
- a) Preserve the containing element
- b) Not rely on any child node to insert your React component
Example
Below is a simple template that could get loaded via ajax into your application
Before
<div class="row">
<div class="col-sm-6">
<div data-container="wysiwyg">
<h1>Sample Heading</h1>
<p>Sample Text</p>
</div>
</div>
</div>
After
You may want to extract the inner html from the data-container
attribute, store it and then pass
it as a prop to your injected RichTextEditor
.
<div class="row">
<div class="col-sm-6">
<div data-container="wysiwyg">
<RichTextEditor html={"<h1>Sample heading</h1><p>Sample Text</p>"} />
</div>
</div>
</div>
Setup
In your instructions object, you must specify replaceChildren: true
.
var React = require('react');
var HtmlToReact = require('html-to-react');
var HtmlToReactParser = require('html-to-react').Parser;
var htmlToReactParser = new HtmlToReactParser();
var htmlInput = '<div><div data-test="foo"><p>Text</p><p>Text</p></div></div>';
var htmlExpected = '<div><div data-test="foo"><h1>Heading</h1></div></div>';
var isValidNode = function () {
return true;
};
var processNodeDefinitions = new HtmlToReact.ProcessNodeDefinitions(React);
var processingInstructions = [
{
replaceChildren: true,
shouldProcessNode: function (node) {
return node.attribs && node.attribs['data-test'] === 'foo';
},
processNode: function (node, children, index) {
return React.createElement('h1', {key: index,}, 'Heading');
}
},
{
shouldProcessNode: function (node) {
return true;
},
processNode: processNodeDefinitions.processDefaultNode,
},
];
var reactComponent = parser.parseWithInstructions(
htmlInput, isValidNode, processingInstructions);
var reactHtml = ReactDOMServer.renderToStaticMarkup(
reactComponent);
assert.equal(reactHtml, htmlExpected);
Tests & Coverage
Test locally: $ npm test
Test with coverage and report coverage to Coveralls: $ npm run test-coverage
Test with coverage and open HTML report: $ npm run test-html-coverage