Library / SDK
software-mansion/react-native-enriched-html avatar
software-mansion/react-native-enriched-html

react-native-enriched-html: rich text editing where the document is HTML

HTML-based Rich Text solution for React Native

1,392 stars72 forksCMIT

At a glance

What is it?
react-native-enriched-html is an MIT-licensed Software Mansion library that gives React Native a native rich text input and display pair driven by HTML content and a shared styling API. The judgement is that the uncontrolled input is the design decision worth understanding, and that the New Architecture requirement is the constraint that decides who can use it.
Who is it for?
react-native-enriched-html fits a React Native team that needs a WYSIWYG editor, needs the edited document to be HTML rather than a proprietary structure, and wants the editor and the read-only view to look identical. It does not fit a project still on the old React Native architecture, since the components are native and support the New Architecture only, and it does not fit a team that wants React state to own the document, because the input is deliberately uncontrolled.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The input does not own its value, and that is the design

react-native-enriched-html is described as a powerful React Native Rich Text solution, and its four headline properties are: fully native input and display components that support the New Architecture only, HTML-based parsing with live synchronous text styling, fully customizable styles for UI integration, and solid mobile and Web support.

The first component is `EnrichedTextInput`, the rich text input, and the important thing about it is that it is an uncontrolled input. It does not use any state or props to store its value, and instead directly interacts with the underlying platform-specific components. The documentation credits this with making the component performant and simple to use while offering complex and advanced features no other solution has.

That decision has consequences in both directions. On the positive side, there is no controlled value to thread through, no re-render on every keystroke, and no risk of the classic controlled-input lag. On the negative side, reading the current content is not a render-time value, and a parent that wants to know the document has to ask for it rather than receive it.

The second component is `EnrichedText`, the display component, designed to work with `EnrichedTextInput`. It renders any HTML generated by the input, and a shared customizable styling API is meant to guarantee 1:1 visual consistency between editing and displaying. That pairing is the reason to use this library rather than a text input plus a separate renderer: the same style definitions drive both surfaces, so a document does not look different depending on whether you are editing it or reading it.

HTML as the document format, which is also the compatibility boundary

The HTML-based parsing with live, synchronous text styling is the second headline property, and it is the one that determines what content you can put through it.

The value of an HTML document format is straightforward. The document that comes out of the editor is markup, not a proprietary tree with custom node types, so it can be stored, transported, indexed and rendered elsewhere. A backend can accept it, a web client can display it, and a search index can treat it as text.

The cost is that the parser is a parser, not a browser engine. It handles a subset of HTML, and the subset is defined by the library rather than by the HTML specification. Anything the parser does not implement will not appear, and anything the parser implements imperfectly will render differently from a browser.

For a team that already produces HTML from a rich text editor elsewhere, or that has content in a CMS, this is a good fit. The library becomes the piece that takes existing markup and makes it editable on a phone. For a team that wants a full document editor with tables, nested lists and arbitrary block structure, the subset question is the one to answer first.

The synchronous part of the styling claim is also worth noting. Live, synchronous text styling means the styled text is applied as it is typed rather than after a round trip through JavaScript state, which is the same reason the input is uncontrolled. The styling is applied in the native layer, next to the text.

The screenshot in the README shows the demo application, and the documentation is described as filled with interactive examples.

A native library with three platform layers

The repository layout makes the engineering approach obvious. There is an `ios/` directory and an `android/` directory, plus a `cpp/` directory for the shared native code, and a `Package.swift` file and a `ReactNativeEnrichedHtml.podspec` at the root for the two iOS integration routes.

The primary language of the repository is listed as C, which is consistent with a shared C++ core under `cpp/` that both platform layers sit on, with the platform-specific parts in Swift and Kotlin or Java under `ios/` and `android/`.

The `src/` directory holds the React Native side, and the `exports` map in `package.json` is where the platform split is made visible. The root export has a `react-native` condition that points at `src/index.native.tsx` for the native build, and a default that points at `src/index.js` for the web build, with separate type declarations for each. So the same public API is served by two implementations, and the bundler picks the right one from the `react-native` condition.

The published `files` array is worth reading because it shows what actually ships. It includes `src`, `lib`, `android`, `ios`, `cpp`, `Package.swift`, the podspec and `react-native.config.js`, with a set of negations that keep build output and Gradle wrapper files out of the package, along with `__tests__`, `__fixtures__`, `__mocks__` and dotfiles. Shipping the native source rather than prebuilt binaries is the norm for a React Native library with platform code, and it means the consumer's build system compiles it.

The `sideEffects` field is set to `"**/*.css"`, which is an interesting detail. It tells the bundler that the only files with side effects are the stylesheets, so the JavaScript can be tree-shaken freely while the CSS imports are preserved. That is what makes the shared styling API able to coexist with a bundler that optimises aggressively.

The documentation is the product surface here

The README is short, and everything of substance is delegated to the documentation site, which is a reasonable choice for a library with this much surface area.

Installation is handled by a link to detailed installation instructions at `docs.swmansion.com/react-native-enriched-html/#installation`. Compatibility is handled by a separate link to a full list of compatible React Native versions at `docs.swmansion.com/react-native-enriched-html/misc/compatibility/#supported-react-native-versions`. And the main documentation link covers usage guides, API references, known limitations and the contributing guide.

The known limitations page is the one to read first for anyone evaluating this, because the README's praise is unqualified and the boundaries are not in the README itself.

What the README does state about compatibility is that the library offers stable support for iOS, Android and Web at the moment, and that the native components support the New Architecture only. That last constraint is the significant one. React Native's New Architecture is the Fabric and TurboModules based renderer, and a library built on native components for it does not run on the old architecture. For a project that has already migrated, that is a non-issue. For a project on the old architecture, it is a blocker rather than a setting to change.

The examples are shipped rather than only described. The source code for the example mobile and web apps is under the `apps` directory, and the scripts in `package.json` point at them, with `example` and `example-web` targeting the two workspaces. The `docs/` directory has its own install and start scripts, so the documentation site itself is a workspace in the monorepo.

The tooling around it is conventional and well maintained. There is a `turbo.json` for task orchestration, a `lefthook.yml` for git hooks, a `babel.config.js`, an `eslint.config.mjs`, `tsconfig.json` alongside `tsconfig.base.json` and `tsconfig.build.json`, a `.maestro/` directory for end-to-end tests, a `.playwright/` directory for web testing, and a `yarn.lock` with a `.yarnrc.yml`.

Where the approach stops working

There are three boundaries that matter in practice, and only one of them is stated in the README.

The first is the New Architecture requirement, already noted. It is a hard compatibility constraint, and the version list is maintained on a separate documentation page, which means it changes as React Native moves and the README does not.

The second is the HTML subset. A library that parses HTML and applies styles to it is doing two things at once, and each has its own limits. The parser decides what markup is understood, and the styling layer decides what can be expressed visually. A backend that sends arbitrary HTML from a content management system will send things this library does not handle, and the failure will be silent in the sense that the content will simply not appear. The known limitations page is where the project describes this, and the README does not summarise it.

The third is the uncontrolled input, and it is the one that surprises people. If your application needs to know the current document, for autosave, for a dirty-state indicator, or for sending content to a server on submit, you have to ask the component rather than read it from props. That is workable and it is how native inputs behave, but it is a different programming model from a controlled React Native `TextInput`, and code written against a controlled model will need restructuring.

There is also a project-level point. The library is built by Software Mansion, a company that says it has been building web and mobile apps since 2012 and is a Core React Native Contributor. The library is MIT licensed, and the repository notes that it is sponsored by Filament. The commercial context is worth knowing because the company offers commercial support and contracting for React Native work, and the library is presented as a product of a consultancy rather than a hobby project. That generally means better maintenance, and it also means the API follows the priorities of a development agency.

Editorial conclusion

react-native-enriched-html fits a React Native team that needs a WYSIWYG editor, needs the edited document to be HTML rather than a proprietary structure, and wants the editor and the read-only view to look identical. It does not fit a project still on the old React Native architecture, since the components are native and support the New Architecture only, and it does not fit a team that wants React state to own the document, because the input is deliberately uncontrolled. Verify first that your React Native version is on the supported list, which the documentation keeps as a separate compatibility page, that the HTML your backend produces is within the subset the parser handles, since the library is HTML-based rather than a general HTML renderer, and that the platform you target has a stable build, given that the native layers are in `ios/`, `android/` and `cpp/` and the project ships a podspec and a Swift package.

Frequently asked questions

How do I install react-native-enriched-html in a React Native project?

The README points to detailed installation instructions at `docs.swmansion.com/react-native-enriched-html/#installation`. Because the components are native, the install covers the iOS, Android and Web parts of the project rather than a single JavaScript dependency.

Does react-native-enriched-html work with the old React Native architecture?

No. The README states that the components are fully native and support the New Architecture only. The library offers stable support for iOS, Android and Web, and the full list of compatible React Native versions is kept on a separate compatibility page in the documentation.

What are EnrichedTextInput and EnrichedText?

`EnrichedTextInput` is the rich text input component and it is an uncontrolled input, so it does not use state or props to store its value and instead interacts directly with the underlying platform-specific components. `EnrichedText` is the display component designed to work with it, rendering the HTML the input generates.

How does react-native-enriched-html keep editing and display looking the same?

Through a shared, customizable styling API that the documentation describes as guaranteeing 1:1 visual consistency between editing and displaying. The package metadata also marks only `**/*.css` as having side effects, so the stylesheets survive tree shaking while the JavaScript is optimised.

Where are the examples for react-native-enriched-html?

The source code for the example mobile and web apps is under the `apps` directory, and the `package.json` scripts `example` and `example-web` run the two workspaces. The documentation site also carries interactive examples of the library's capabilities.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. software-mansion/react-native-enriched-html on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/software-mansion-react-native-enriched-html.svg)](https://hysenlabs.com/projects/software-mansion-react-native-enriched-html)

Was this useful?