{"id":11669,"library":"react-contenteditable","title":"React ContentEditable Component","description":"react-contenteditable is a React component that simplifies the integration of the native `contenteditable` HTML attribute into React applications. It provides a controlled component approach, allowing developers to manage the `innerHTML` of an editable HTML element (like a `div` or `article`) via React state. The package, currently at version 3.3.7, addresses many common challenges associated with `contenteditable` in React, such as cursor jumping and state synchronization, often encountered when directly managing DOM mutations. It abstracts the use of `dangerouslySetInnerHTML`, providing a safer and more idiomatic React interface. While the component is designed to mitigate typical `contenteditable` pitfalls, users should be aware of inherent complexities like input sanitization to prevent XSS attacks and managing rich text pasting. The library ships with TypeScript types.","status":"active","version":"3.3.7","language":"javascript","source_language":"en","source_url":"https://github.com/lovasoa/react-contenteditable","tags":["javascript","react-component","contenteditable","editable","html","react","typescript"],"install":[{"cmd":"npm install react-contenteditable","lang":"bash","label":"npm"},{"cmd":"yarn add react-contenteditable","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-contenteditable","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for React applications.","package":"react","optional":false}],"imports":[{"note":"ContentEditable is exported as a default module. Avoid named import syntax.","wrong":"import { ContentEditable } from 'react-contenteditable'","symbol":"ContentEditable","correct":"import ContentEditable from 'react-contenteditable'"},{"note":"For CommonJS environments, use the direct require call as it's a default export.","wrong":"const { ContentEditable } = require('react-contenteditable')","symbol":"ContentEditable","correct":"const ContentEditable = require('react-contenteditable')"}],"quickstart":{"code":"import React from 'react';\nimport ContentEditable from 'react-contenteditable';\n\nclass MyEditor extends React.Component {\n  constructor() {\n    super();\n    this.contentEditable = React.createRef();\n    this.state = { html: \"<p><b>Hello</b> <i>World</i></p>\" };\n  }\n\n  handleChange = (evt) => {\n    this.setState({ html: evt.target.value });\n  };\n\n  // Optional: Sanitize content on blur to prevent XSS or unwanted formatting\n  handleBlur = () => {\n    console.log('Final content:', this.state.html);\n    // In a real app, you might sanitize or save the content here\n    // E.g., this.setState({ html: sanitizeHtml(this.state.html) });\n  };\n\n  render() {\n    return (\n      <ContentEditable\n        innerRef={this.contentEditable}\n        html={this.state.html} // innerHTML of the editable div\n        disabled={false}      // use true to disable editing\n        onChange={this.handleChange} // handle innerHTML change\n        onBlur={this.handleBlur}\n        tagName='article'     // Use a custom HTML tag (uses a div by default)\n        suppressContentEditableWarning={true} // Suppress React's contentEditable warning\n        style={{ border: '1px solid #ccc', minHeight: '100px', padding: '10px' }}\n      />\n    );\n  }\n}\n\nexport default MyEditor;","lang":"javascript","description":"Demonstrates a basic rich text editor using a class component, managing HTML content in state, and handling changes."},"warnings":[{"fix":"Instead, utilize the `useRef` hook to store and update the editable content (e.g., `text.current = evt.target.value`), as this avoids unnecessary re-renders that interfere with native `contenteditable` behavior. The `html` prop should then receive `text.current`.","message":"Using React's `useState` hook directly to manage the content of `<ContentEditable />` often leads to unexpected behavior, cursor jumping, or issues with input synchronization.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"This warning indicates a conflict between React's virtual DOM and direct DOM mutations. If you are intentionally managing the content via the component's callbacks, you can suppress it by adding the prop `suppressContentEditableWarning={true}` to your `ContentEditable` component.","message":"When integrating `contenteditable` elements in React, you might encounter the console warning: 'Warning: A component is `contentEditable` and contains children managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated.'","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always sanitize the HTML content before rendering or saving it. Libraries like 'sanitize-html' can be used to whitelist allowed HTML tags and attributes, both client-side on change and crucially, server-side before persisting data. The component's advanced example demonstrates sanitization.","message":"Unsanitized HTML input into `contenteditable` elements, particularly when using `dangerouslySetInnerHTML` (which `react-contenteditable` abstracts), poses a significant cross-site scripting (XSS) vulnerability. Attackers could embed malicious scripts.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Implement a paste handler (e.g., using `onPaste` prop) to process clipboard data, stripping formatting and inserting plain text or sanitized HTML. Refer to `contenteditable` best practices or the library's advanced examples for robust paste handling.","message":"Pasting rich text content directly into a `contenteditable` element often retains original formatting, leading to inconsistent styles or unwanted HTML tags being introduced, instead of plain text.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"If you are intentionally managing the content via `react-contenteditable`'s props, you can suppress this warning by adding `suppressContentEditableWarning={true}` to the `ContentEditable` component.","cause":"React warns about potential conflicts when its virtual DOM manages children within an element whose content can also be directly edited by the browser via `contenteditable`.","error":"Warning: A component is contentEditable and contains children managed by React."},{"fix":"Ensure `innerRef` is initialized with `React.createRef()` in class components or `useRef(null)` in functional components, and that the ref is only accessed after the component has mounted (e.g., within `useEffect` with an empty dependency array or after render in class components).","cause":"The `innerRef` property was accessed before it was properly assigned to a DOM element, often due to incorrect initialization or timing, especially with functional components.","error":"TypeError: Cannot read properties of null (reading 'current')"},{"fix":"Refactor to use `useRef` to store the HTML content. Update `text.current` within the `onChange` handler and pass `text.current` to the `html` prop. The `ContentEditable` component will then manage the DOM updates more gracefully without triggering unwanted React re-renders for every keystroke.","cause":"Direct use of `useState` with `ContentEditable` causes frequent re-renders that interfere with the browser's native cursor positioning and input handling within the editable element.","error":"Contenteditable doesn't work properly with React State (writes in the opposite way) / Cursor jumps to the end / Input state out of sync"}],"ecosystem":"npm"}