React Simple WYSIWYG Editor
react-simple-wysiwyg is a lightweight and performant React component for creating basic WYSIWYG rich text editing experiences. Currently at version 3.4.1, it focuses on providing essential editing functionality without the extensive features and overhead of more complex editors like Slate.js, Tiptap, CKEditor, or TinyMCE. Its key differentiators include a small bundle size (~9kb, ~4kb gzipped), ease of configuration, and extensibility for simple custom buttons. The library explicitly states it does not sanitize HTML, provide advanced features like table or image editors, or alter HTML generated by the browser, requiring developers to handle these aspects externally (e.g., using `sanitize-html` for sanitization). While it utilizes the deprecated `document.execCommand` API, it justifies this by noting the lack of a modern alternative and its continued use by many popular WYSIWYG editors. The project appears to be actively maintained, with recent updates and open issues on GitHub.
Common errors
-
TypeError: Editor is not a function
cause Attempting to use `Editor` as a named import when it is the default export of the package.fixChange the import statement from `import { Editor } from 'react-simple-wysiwyg';` to `import Editor from 'react-simple-wysiwyg';` -
A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
cause The `value` prop provided to the `Editor` component changes between `undefined` and a string, typically because the initial state is not set or is conditionally applied.fixEnsure the `value` prop is always provided and managed by React state, even if it's an empty string initially. For example, use `const [html, setHtml] = useState('');` to initialize the content as an empty string. -
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `YourComponent`.
cause This error often occurs when toolbar button components (e.g., `BtnBold`, `BtnItalic`) are not imported as named exports or are used incorrectly outside the `<Toolbar>` component.fixVerify that all toolbar-related components are correctly imported as named exports (e.g., `import { Toolbar, BtnBold } from 'react-simple-wysiwyg';`) and are rendered as children of the `<Toolbar>` component within the `<Editor>`.
Warnings
- deprecated The underlying `document.execCommand` API, which `react-simple-wysiwyg` heavily relies on for rich text operations, is deprecated. While currently functional across most browsers, its long-term support and future behavior are uncertain, and it lacks a modern, standardized replacement.
- gotcha This editor explicitly DOES NOT sanitize HTML input. User-provided content, especially if sourced from untrusted inputs, must be sanitized externally (e.g., using `sanitize-html`) before being rendered or stored, to prevent Cross-Site Scripting (XSS) vulnerabilities.
- gotcha The editor does not include advanced features like table editing, image uploading/embedding, spell check, or complex media integration. It focuses on basic text formatting.
- gotcha By default, the editor does not modify or normalize the raw HTML generated by the browser's `contenteditable` element. This can sometimes result in 'dirty' or inconsistent HTML output depending on user interactions and browser specifics.
Install
-
npm install react-simple-wysiwyg -
yarn add react-simple-wysiwyg -
pnpm add react-simple-wysiwyg
Imports
- Editor
import { Editor } from 'react-simple-wysiwyg'; // Editor is the default export, not named.import Editor from 'react-simple-wysiwyg';
- Toolbar
import Toolbar from 'react-simple-wysiwyg'; // Toolbar is a named export.
import { Toolbar } from 'react-simple-wysiwyg'; - BtnBold
const { BtnBold } = require('react-simple-wysiwyg'); // This package is ESM-first and ships TypeScript types. Prefer ESM imports.import { BtnBold } from 'react-simple-wysiwyg'; - createButton
import { createButton } from 'react-simple-wysiwyg';
Quickstart
import { useState } from 'react';
import Editor from 'react-simple-wysiwyg';
function MyRichTextEditor() {
const [htmlContent, setHtmlContent] = useState('Write your <b>rich text</b> here!');
// The onChange event provides an event object with e.target.value containing the HTML string.
function handleChange(e: { target: { value: string } }) {
setHtmlContent(e.target.value);
}
return (
<div style={{ maxWidth: '800px', margin: '20px auto', padding: '15px', border: '1px solid #ddd', borderRadius: '8px' }}>
<h2>My Simple Editor</h2>
<Editor
value={htmlContent}
onChange={handleChange}
containerProps={{ style: { marginTop: '15px', border: '1px solid #ccc', borderRadius: '4px' } }}
placeholder="Start typing..."
/>
<p style={{ marginTop: '20px', fontSize: '0.9em', color: '#666' }}>
Current HTML Output (for demonstration):
</p>
<pre style={{ background: '#f8f8f8', padding: '10px', borderRadius: '4px', overflowX: 'auto' }}>
{htmlContent}
</pre>
</div>
);
}
// To render this in a typical React application:
// import React from 'react';
// import ReactDOM from 'react-dom/client';
// const root = ReactDOM.createRoot(document.getElementById('root')!);
// root.render(<React.StrictMode><MyRichTextEditor /></React.StrictMode>);