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.
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.
react-codemirror is the original wrapper for CodeMirror 5.
// 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.
// 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)}
/>
);
}
react-codemirror primarily exposes a controlled component interface.
value prop dictates the editor content.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.
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' }}
/>
react-codemirror targets CodeMirror 5 exclusively.
CodeMirror object or a specific import structure common in CM5.// 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.
// react-codemirror2: Loading modes
import 'codemirror/mode/javascript/javascript';
import 'codemirror/theme/material.css';
// Same CM5 dependency constraints as the original
react-codemirror struggles with React 16+ strict mode.
componentWillReceiveProps trigger warnings.// 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.
componentDidUpdate more effectively to sync props.// react-codemirror2: Improved prop syncing
// Still requires careful management of 'value' vs 'onBeforeChange'
<Controlled
value={externalValue}
onBeforeChange={(e, d, val) => setValue(val)}
/>
You have an internal tool built 4 years ago using CodeMirror 5.
react-codemirror2// Legacy maintenance
import { UnControlled as CodeMirror } from 'react-codemirror2';
// Stick with what works, avoid upgrading CM core
You are building a competitor to CodeSandbox or a new IDE.
@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)}
/>
You need a lightweight editor for a blog post draft.
react-codemirror2 (if CM5 is already in deps)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)}
/>
| Feature | react-codemirror | react-codemirror2 |
|---|---|---|
| Status | ❌ Unmaintained / Legacy | ⚠️ Maintenance Mode (Legacy CM5) |
| Component API | Single Controlled Component | Controlled & UnControlled exports |
| React Lifecycle | ⚠️ Warnings in Strict Mode | ✅ Better Prop Sync |
| Cursor Stability | ❌ Prone to jumps on re-render | ⚠️ Improved but still tricky |
| CodeMirror Ver | v5 | v5 |
| Recommendation | 🛑 Do Not Use | ⚠️ Legacy Support Only |
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.
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.
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.
The excellent CodeMirror editor as a React.js component.
Live demo: JedWatson.github.io/react-codemirror
To build the examples locally, run:
npm install
npm start
Then open localhost:8000 in a browser.
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
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'));
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">.
focus focuses the CodeMirror instancegetCodeMirror 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).
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 editorcodeMirrorInstance Function provides a specific CodeMirror instance (defaults to require('codemirror'))defaultValue String provides a default (not change tracked) value to the editorname String sets the name of the editor input fieldoptions Object options passed to the CodeMirror instanceonChange Function (newValue) called when a change is madeonCursorActivity Function (codemirror) called when the cursor is movedonFocusChange Function (focused) called when the editor is focused or loses focusonScroll Function (scrollInfo) called when the editor is scrolledpreserveScrollPosition Boolean=false preserve previous scroll position after updating valuevalue String the editor valueSee the CodeMirror API Docs for the available options.
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:
codemirror package dependency (in addition to react-codemirror)react-codemirror itselfmode option in the options objectvar 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.
Copyright (c) 2016 Jed Watson. MIT Licensed.