rehype-react
rehype-react is a `rehype` plugin designed to compile HTML abstract syntax trees (hast) into JSX elements, enabling the rendering of HTML content within various JSX runtimes. It currently supports React, Preact, Solid, Svelte, and Vue. The current stable version is 8.0.0. The project maintains an active release cadence with frequent patch and minor updates, and major versions are released to introduce significant architectural changes, such as the move to ESM or multi-framework support. A key differentiator is its integration within the `unified` ecosystem, allowing developers to leverage a rich pipeline of AST transformations on HTML content before it's rendered. This provides more control compared to simpler solutions like `react-markdown` and offers an alternative to `react-remark` for HTML processing.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/rehype-react/index.js from ... not supported.
cause Attempting to import rehype-react using `require()` in a CommonJS module, but rehype-react is an ESM-only package.fixChange `const rehypeReact = require('rehype-react')` to `import rehypeReact from 'rehype-react'` and ensure your project is configured for ESM (e.g., by adding `"type": "module"` to `package.json`). -
TypeError: Cannot read properties of undefined (reading 'Fragment')
cause This error typically occurs in v8.0.0 when passing individual `Fragment` and `createElement` imports to `rehypeReact` options, which is no longer supported.fixInstead of `{Fragment, createElement}`, pass an object containing the JSX runtime functions, usually imported as `import * as production from 'react/jsx-runtime'` and then `.use(rehypeReact, production)`. -
TypeError: `fixTableCellAlign` is not a valid option
cause Using the deprecated option name `fixTableCellAlign` with rehype-react v8.0.0 or later.fixRename the option `fixTableCellAlign` to `tableCellAlignToStyle` in your plugin configuration. -
ReferenceError: process is not defined
cause Attempting to run a Node.js specific global (`process`) in a browser environment without proper polyfills or environment setup (e.g., Vite/Webpack configurations for browser).fixEnsure your build tools correctly polyfill Node.js globals for browser contexts, or conditionally access `process.version` only in Node.js environments. For example, use `typeof process !== 'undefined' ? process.version : 'browser'`.
Warnings
- breaking rehype-react v8.0.0 and later requires Node.js version 16 or higher. Older Node.js versions are not supported.
- breaking rehype-react v7.0.0 and later is an ESM-only package. Attempting to `require()` it in a CommonJS module will result in a runtime error.
- breaking The `rehypeReact` plugin options for specifying `Fragment` and `createElement` have changed in v8.0.0. Instead of passing individual components, you must now pass an object containing the JSX runtime functions (e.g., `Fragment`, `jsx`, `jsxs`) from `react/jsx-runtime`.
- breaking The option `fixTableCellAlign` was renamed to `tableCellAlignToStyle` in v8.0.0.
- breaking The types for rehype-react were significantly improved in v7.0.0. While this is generally beneficial, it could introduce breaking changes if your TypeScript code was relying on previously looser typings or internal structures.
Install
-
npm install rehype-react -
yarn add rehype-react -
pnpm add rehype-react
Imports
- rehypeReact
const rehypeReact = require('rehype-react')import rehypeReact from 'rehype-react'
- production (JSX runtime object)
import {Fragment, createElement} from 'react'import * as production from 'react/jsx-runtime'
- unified
import unified from 'unified'
import { unified } from 'unified'
Quickstart
import { Fragment, createElement, useEffect, useState } from 'react';
import * as prod from 'react/jsx-runtime';
import rehypeParse from 'rehype-parse';
import rehypeReact from 'rehype-react';
import { unified } from 'unified';
// To run this example:
// npm install react react-dom rehype-parse rehype-react unified
// @ts-expect-error: The react types might be missing for `prod` object
const production = { Fragment: prod.Fragment, jsx: prod.jsx, jsxs: prod.jsxs };
const htmlContent = `<h2>Hello, world from rehype-react!</h2>\n<p>This paragraph contains <em>emphasized</em> text and a <a href="#">link</a>.</p>\n<p>Current Node.js version is ${process.version}.</p>`;
/**
* A React hook to process HTML content using rehype-react.
* @param {string} text The HTML string to process.
* @returns {JSX.Element} A React component tree.
*/
function useHtmlProcessor(text) {
const [Content, setContent] = useState(createElement(Fragment));
useEffect(
function () {
(async function () {
const file = await unified()
.use(rehypeParse, { fragment: true })
.use(rehypeReact, production)
.process(text);
setContent(file.result);
})();
},
[text]
);
return Content;
}
export default function App() {
return useHtmlProcessor(htmlContent);
}
// In a typical React app, you would render <App /> using ReactDOM.createRoot:
// import ReactDOM from 'react-dom/client';
// const root = ReactDOM.createRoot(document.getElementById('root'));
// root.render(<App />);