react-codemirror vs react-codemirror2
Integrating CodeMirror 5 into React Applications
react-codemirrorreact-codemirror2Similar Packages:

Integrating CodeMirror 5 into React Applications

react-codemirror and react-codemirror2 are React component wrappers for the CodeMirror 5 code editor library. They allow developers to embed a feature-rich text editor with syntax highlighting, linting, and theming into React applications. While both packages target CodeMirror 5, they differ in maintenance history, API stability, and community adoption. react-codemirror is the original wrapper, while react-codemirror2 emerged as a maintained fork to address bugs and add React lifecycle compatibility. However, both are now considered legacy solutions in the context of CodeMirror 6.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-codemirror01,557-699 years agoMIT
react-codemirror201,70471.5 kB947 months agoMIT

react-codemirror vs react-codemirror2: Legacy CodeMirror 5 Wrappers

Both react-codemirror and react-codemirror2 serve the same fundamental purpose: embedding the CodeMirror 5 editor into a React application. They abstract away the direct DOM manipulation required by CodeMirror, exposing it as a React component with props for value, options, and events. However, their trajectories diverge significantly in terms of maintenance and long-term viability.

🏗️ Maintenance and Lifecycle Status

react-codemirror is the original wrapper for CodeMirror 5.

  • It saw early adoption but has since become stagnant.
  • Issues and pull requests often go unaddressed for long periods.
  • It does not actively track React's evolving lifecycle methods.
// react-codemirror: Basic usage
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';

function Editor({ value, onChange }) {
  const options = { lineNumbers: true, mode: 'javascript' };
  
  return (
    <CodeMirror
      value={value}
      options={options}
      onChange={onChange}
    />
  );
}

react-codemirror2 was created as a fork to fix bugs and improve stability.

  • It received more consistent updates for a longer period.
  • It handles React prop updates and unmounting more reliably.
  • Despite being "better," it is also effectively in maintenance mode now.
// react-codemirror2: Basic usage
import { UnControlled as CodeMirror } from 'react-codemirror2';
import 'codemirror/lib/codemirror.css';

function Editor({ value, onChange }) {
  const options = { lineNumbers: true, mode: 'javascript' };
  
  return (
    <CodeMirror
      value={value}
      options={options}
      onBeforeChange={(editor, data, value) => onChange(value)}
    />
  );
}

⚙️ API Design: Controlled vs Uncontrolled

react-codemirror primarily exposes a controlled component interface.

  • The value prop dictates the editor content.
  • Updating the value prop forces the editor to refresh, which can cause cursor jumps if not handled carefully.
  • Event handlers like onChange pass the new value directly.
// react-codemirror: Controlled flow
<CodeMirror
  value={code}
  onChange={(newCode) => setCode(newCode)}
  options={{ mode: 'python' }}
/>

react-codemirror2 explicitly separates Controlled and Uncontrolled components.

  • You import Controlled or UnControlled based on your needs.
  • UnControlled manages its own internal state, reducing React render cycles for typing.
  • Controlled requires careful handling of onBeforeChange to avoid cursor issues.
// react-codemirror2: UnControlled flow
import { UnControlled as CodeMirror } from 'react-codemirror2';

<CodeMirror
  value={initialCode}
  onBeforeChange={(editor, data, newCode) => {
    // Only update React state if needed, e.g., on blur or save
  }}
  options={{ mode: 'python' }}
/>

🧩 CodeMirror Version Support

react-codemirror targets CodeMirror 5 exclusively.

  • It relies on the global CodeMirror object or a specific import structure common in CM5.
  • It does not support the modular architecture of CodeMirror 6.
  • Adding languages or themes requires loading external scripts or CSS manually.
// react-codemirror: Loading modes
import 'codemirror/mode/javascript/javascript';
import 'codemirror/theme/material.css';

// Usage relies on CM5 global or module side-effects

react-codemirror2 also targets CodeMirror 5 exclusively.

  • It shares the same underlying dependency limitations.
  • While more stable, it cannot leverage CodeMirror 6's performance improvements or extension system.
  • Migration to CM6 requires a complete rewrite of the editor integration.
// react-codemirror2: Loading modes
import 'codemirror/mode/javascript/javascript';
import 'codemirror/theme/material.css';

// Same CM5 dependency constraints as the original

⚠️ Known Pain Points

react-codemirror struggles with React 16+ strict mode.

  • Lifecycle methods like componentWillReceiveProps trigger warnings.
  • Cursor position often resets when the parent component re-renders.
  • Memory leaks can occur if the editor instance isn't properly destroyed on unmount.
// react-codemirror: Cursor jump issue
// When 'value' prop updates, cursor often goes to end of line
<CodeMirror value={externalValue} onChange={setValue} />

react-codemirror2 mitigates some lifecycle issues but not all.

  • It uses componentDidUpdate more effectively to sync props.
  • However, it still suffers from the fundamental mismatch between React's virtual DOM and CodeMirror's direct DOM manipulation.
  • Performance degrades with very large files due to CM5 limitations.
// react-codemirror2: Improved prop syncing
// Still requires careful management of 'value' vs 'onBeforeChange'
<Controlled
  value={externalValue}
  onBeforeChange={(e, d, val) => setValue(val)}
/>

🌱 When to Use These (and When Not To)

Scenario 1: Maintaining a Legacy Admin Panel

You have an internal tool built 4 years ago using CodeMirror 5.

  • Choice: react-codemirror2
  • Why? It's more stable than the original. Rewriting the whole editor stack isn't worth the cost for an internal tool.
// Legacy maintenance
import { UnControlled as CodeMirror } from 'react-codemirror2';
// Stick with what works, avoid upgrading CM core

Scenario 2: Building a New Code Editor Product

You are building a competitor to CodeSandbox or a new IDE.

  • Choice: Neither
  • Why? CodeMirror 5 is in maintenance mode. You need CodeMirror 6 for performance and extensibility.
  • Alternative: @uiw/react-codemirror
// Modern approach with CodeMirror 6
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

<CodeMirror
  value={code}
  height="500px"
  extensions={[javascript()]}
  onChange={(val) => setCode(val)}
/>

Scenario 3: Simple Markdown Blog Editor

You need a lightweight editor for a blog post draft.

  • ⚠️ Choice: react-codemirror2 (if CM5 is already in deps)
  • Why? If you don't need CM6 features, react-codemirror2 is stable enough. But consider simpler markdown-only editors if syntax highlighting isn't critical.
// Simple integration
<CodeMirror
  value={markdown}
  options={{ mode: 'markdown', lineWrapping: true }}
  onChange={(e, d, v) => setMarkdown(v)}
/>

📊 Summary: Key Differences

Featurereact-codemirrorreact-codemirror2
Status❌ Unmaintained / Legacy⚠️ Maintenance Mode (Legacy CM5)
Component APISingle Controlled ComponentControlled & UnControlled exports
React Lifecycle⚠️ Warnings in Strict Mode✅ Better Prop Sync
Cursor Stability❌ Prone to jumps on re-render⚠️ Improved but still tricky
CodeMirror Verv5v5
Recommendation🛑 Do Not Use⚠️ Legacy Support Only

💡 The Big Picture

react-codemirror is a historical artifact. It served a purpose when React was younger and CodeMirror 5 was the standard. Today, it represents technical debt. Using it introduces risk without offering any advantage over its fork.

react-codemirror2 is the "safe" choice within a dying ecosystem. It fixed the sharp edges of the original wrapper, making it viable for maintaining older applications. However, it does not solve the fundamental limitation: CodeMirror 5 is no longer the future of web-based code editing.

Final Thought: If you are starting fresh, do not choose between these two. Choose a CodeMirror 6 wrapper like @uiw/react-codemirror or codemirror-react. The architectural shift in CM6 (state transactions, extensions) makes old wrappers obsolete. Only reach for react-codemirror2 if you are keeping the lights on for an existing legacy system.

How to Choose: react-codemirror vs react-codemirror2

  • react-codemirror:

    Avoid using react-codemirror for new projects. It is largely unmaintained and lacks support for modern React patterns (like hooks) and newer CodeMirror 5 features. It may still work for legacy applications already locked into this specific version, but migrating to a maintained alternative is strongly recommended to prevent technical debt.

  • react-codemirror2:

    Choose react-codemirror2 only if you are maintaining an existing legacy application that depends on CodeMirror 5 and cannot migrate to CodeMirror 6 immediately. It offers better stability and bug fixes compared to the original react-codemirror. For any new development, prefer modern wrappers like @uiw/react-codemirror that support CodeMirror 6, as CodeMirror 5 is in maintenance mode.

README for react-codemirror

Codemirror

The excellent CodeMirror editor as a React.js component.

Demo & Examples

Live demo: JedWatson.github.io/react-codemirror

To build the examples locally, run:

npm install
npm start

Then open localhost:8000 in a browser.

Installation

The easiest way to use codemirror is to install it from NPM and include it in your own React build process (using Browserify, Webpack, etc).

You can also use the standalone build by including dist/react-codemirror.js in your page. If you use this, make sure you have already included React, and it is available as a global variable.

npm install react-codemirror --save

Usage

Require the CodeMirror component and render it with JSX:

var React = require('react');
var CodeMirror = require('react-codemirror');

var App = React.createClass({
	getInitialState: function() {
		return {
			code: "// Code",
		};
	},
	updateCode: function(newCode) {
		this.setState({
			code: newCode,
		});
	},
	render: function() {
		var options = {
			lineNumbers: true,
		};
		return <CodeMirror value={this.state.code} onChange={this.updateCode} options={options} />
	}
});

React.render(<App />, document.getElementById('app'));

Include the CSS

Ensure that CodeMirror's stylesheet codemirror.css is loaded.

If you're using LESS (similar for Sass) you can import the css directly from the codemirror package, as shown in example.less:

@import (inline) "./node_modules/codemirror/lib/codemirror.css";

If you're using Webpack with the css loader, you can require the codemirror css in your application instead:

require('codemirror/lib/codemirror.css');

Alternatively, you can explicitly link the codemirror.css file from the CodeMirror project in your index.html file, e.g <link href="css/codemirror.css" rel="stylesheet">.

Methods

  • focus focuses the CodeMirror instance
  • getCodeMirror returns the CodeMirror instance, available .

You can interact with the CodeMirror instance using a ref and the getCodeMirror() method after the componentDidMount lifecycle event has fired (including inside the componentDidMount event in a parent Component).

Properties

  • autoFocus Boolean automatically focuses the editor when it is mounted (default false)
  • autoSave Boolean automatically persist changes to underlying textarea (default false)
  • className String adds a custom css class to the editor
  • codeMirrorInstance Function provides a specific CodeMirror instance (defaults to require('codemirror'))
  • defaultValue String provides a default (not change tracked) value to the editor
  • name String sets the name of the editor input field
  • options Object options passed to the CodeMirror instance
  • onChange Function (newValue) called when a change is made
  • onCursorActivity Function (codemirror) called when the cursor is moved
  • onFocusChange Function (focused) called when the editor is focused or loses focus
  • onScroll Function (scrollInfo) called when the editor is scrolled
  • preserveScrollPosition Boolean=false preserve previous scroll position after updating value
  • value String the editor value

See the CodeMirror API Docs for the available options.

Using Language Modes

Several language modes are included with CodeMirror for syntax highlighting.

By default (to optimise bundle size) all modes are not included. To enable syntax highlighting:

  • install the codemirror package dependency (in addition to react-codemirror)
  • require the language modes you wish to make available after you require react-codemirror itself
  • set the mode option in the options object
var React = require('react');
var CodeMirror = require('react-codemirror');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/xml/xml');
require('codemirror/mode/markdown/markdown');

<CodeMirror ... options={{
	mode: 'javascript',
}} />

See the example source for a reference implementation including JavaScript and markdown syntax highlighting.

License

Copyright (c) 2016 Jed Watson. MIT Licensed.