React From DOM: HTML/XML to React Element Converter
react-from-dom is a utility library designed to convert HTML/XML source code strings or existing DOM nodes into React elements. It serves as a safer, more controlled alternative to React's `dangerouslySetInnerHTML`, allowing developers to parse external content and render it as native React components. The current stable version is 0.7.5. The package maintains a steady release cadence, primarily focusing on dependency updates, minor bug fixes, and continuous integration improvements, as seen in the recent 0.7.x releases. Key differentiators include its ability to accept both string and DOM Node inputs, comprehensive options for parsing (e.g., whitespace control, specific selectors, MIME types), and an extensible 'actions' API to modify or replace nodes during conversion, enabling powerful transformations and sanitization workflows not easily achievable with `dangerouslySetInnerHTML`.
Common errors
-
Warning: Each child in a list should have a unique "key" prop.
cause When converting HTML with multiple sibling elements, React requires a unique key for each element in an array to optimize reconciliation. `react-from-dom` might not always generate sufficiently unique or stable keys by default, or the `randomKey` option was used inappropriately.fixFor static content, the default key generation is usually sufficient. For dynamic or complex content, consider providing a stable, unique key via a custom `post` action for the root elements of your parsed content, or set `randomKey: true` only if elements are truly static and order doesn't matter for React's reconciliation. -
TypeError: Cannot read properties of undefined (reading 'toLowerCase') or similar errors related to node properties.
cause This often occurs within `condition` or `pre` actions when `node` is not an `HTMLElement` or `Element` type as expected, but rather a `Text` node or `Comment` node, which lack methods like `toLowerCase` on `nodeName`.fixAdd a check `if (node.nodeType === Node.ELEMENT_NODE)` or `if (node instanceof HTMLElement)` within your action's `condition` or `pre` function before attempting to access element-specific properties. -
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
cause This typically happens if the `convert` function returns a raw DOM node (when `nodeOnly: true` is used with a string input) or an unexpected non-React object type, and React attempts to render it directly.fixEnsure that `nodeOnly` is set to `false` (its default) if you intend to render the output directly in a React component. If `nodeOnly` is true, you must manually process the returned DOM nodes, for example, by appending them to an existing DOM element outside of React's render cycle.
Warnings
- gotcha When parsing untrusted HTML/XML content, always sanitize the input string to prevent XSS (Cross-Site Scripting) vulnerabilities. While `react-from-dom` provides mechanisms like 'actions' for transformation, it does not inherently sanitize input.
- breaking Prior to version 0.7.0, the library might not have fully supported React Fragments or parsing of pure text nodes, leading to unexpected output or errors for certain HTML structures.
- gotcha Using the `randomKey` option for dynamically generated lists or frequently updated content can lead to performance issues and React reconciliation problems. React relies on stable keys to efficiently update list items.
- gotcha When `includeAllNodes` is set to `true` with a string input, `react-from-dom` returns an array of React elements. If `nodeOnly` is also true, it returns a `NodeList`. Incorrectly handling these array/NodeList returns when a single element is expected can lead to rendering issues.
Install
-
npm install react-from-dom -
yarn add react-from-dom -
pnpm add react-from-dom
Imports
- default
const convert = require('react-from-dom');import convert from 'react-from-dom';
- Options
import type { Options } from 'react-from-dom'; - Action
import type { Action } from 'react-from-dom';
Quickstart
import React from 'react';
import convert from 'react-from-dom';
// Example 1: Converting an HTML string
const htmlString = `
<div class="card">
<h3>Welcome to react-from-dom!</h3>
<p>This paragraph has <strong>bold text</strong> and an <a href="#">internal link</a>.</p>
<img src="https://via.placeholder.com/150" alt="Placeholder Image" />
<p style="color: red; font-size: 14px;">Styled content.</p>
</div>
`;
const reactElementFromString = convert(htmlString, {
actions: [
{
condition: (node) => node.nodeName.toLowerCase() === 'a',
pre: (node) => {
if (node instanceof HTMLElement) {
node.setAttribute('target', '_blank'); // Add target='_blank' to links
node.setAttribute('rel', 'noopener noreferrer');
}
return node;
},
},
],
});
// Example 2: Converting an existing DOM Node
const rootDomNode = document.createElement('div');
rootDomNode.id = 'dynamic-root';
const p = document.createElement('p');
p.textContent = 'This content came from a dynamically created DOM node.';
rootDomNode.appendChild(p);
const reactElementFromDomNode = convert(rootDomNode);
const App = () => (
<div>
<h2>Converted from HTML String:</h2>
{reactElementFromString}
<h2>Converted from DOM Node:</h2>
{reactElementFromDomNode}
<p>Note: The link in the first example will open in a new tab due to an 'action'.</p>
</div>
);
export default App;