Top Related Projects
In-browser code editor (version 5, legacy)
Codemirror Component for React.js
React Ace Component
Monaco Editor for React.
A browser based code editor
Quick Overview
react-codemirror2 is a React wrapper for CodeMirror, a versatile text editor implemented in JavaScript for the browser. It provides a flexible and customizable code editing component for React applications, supporting various programming languages and features like syntax highlighting and code folding.
Pros
- Easy integration with React applications
- Supports a wide range of programming languages and themes
- Highly customizable with numerous options and extensions
- Regular updates and active maintenance
Cons
- Learning curve for advanced customization
- Large bundle size when including multiple language modes
- Some performance issues with very large files
- Documentation could be more comprehensive
Code Examples
- Basic usage:
import { Controlled as CodeMirror } from 'react-codemirror2';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/material.css';
import 'codemirror/mode/javascript/javascript';
function Editor() {
return (
<CodeMirror
value="console.log('Hello, world!');"
options={{
mode: 'javascript',
theme: 'material',
lineNumbers: true
}}
onBeforeChange={(editor, data, value) => {
console.log('new value:', value);
}}
/>
);
}
- Using multiple language modes:
import { Controlled as CodeMirror } from 'react-codemirror2';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/python/python';
function MultiLanguageEditor() {
const [language, setLanguage] = useState('javascript');
return (
<>
<select onChange={(e) => setLanguage(e.target.value)}>
<option value="javascript">JavaScript</option>
<option value="python">Python</option>
</select>
<CodeMirror
value={language === 'javascript' ? 'console.log("Hello")' : 'print("Hello")'}
options={{
mode: language,
lineNumbers: true
}}
/>
</>
);
}
- Implementing code folding:
import { Controlled as CodeMirror } from 'react-codemirror2';
import 'codemirror/lib/codemirror.css';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/foldgutter';
function FoldableEditor() {
return (
<CodeMirror
value={`function example() {
if (true) {
console.log('Foldable code');
}
}`}
options={{
mode: 'javascript',
lineNumbers: true,
foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
}}
/>
);
}
Getting Started
-
Install the package:
npm install react-codemirror2 codemirror
-
Import and use in your React component:
import { Controlled as CodeMirror } from 'react-codemirror2'; import 'codemirror/lib/codemirror.css'; import 'codemirror/mode/javascript/javascript'; function MyEditor() { return ( <CodeMirror value="// Your code here" options={{ mode: 'javascript', lineNumbers: true }} onBeforeChange={(editor, data, value) => { // Handle value change }} /> ); }
-
Add desired language modes and themes by importing them separately.
Competitor Comparisons
In-browser code editor (version 5, legacy)
Pros of CodeMirror 5
- More mature and stable, with a larger ecosystem of plugins and themes
- Offers broader browser compatibility, including support for older browsers
- Provides more extensive documentation and examples
Cons of CodeMirror 5
- Larger bundle size, which may impact performance in some applications
- Less seamless integration with React components and state management
- Requires more setup and configuration for React-specific use cases
Code Comparison
React-CodeMirror2:
import { Controlled as CodeMirror } from 'react-codemirror2';
<CodeMirror
value={code}
options={{
mode: 'javascript',
theme: 'material',
lineNumbers: true
}}
onBeforeChange={(editor, data, value) => {
setCode(value);
}}
/>
CodeMirror 5:
import CodeMirror from 'codemirror';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/lib/codemirror.css';
useEffect(() => {
const editor = CodeMirror.fromTextArea(textareaRef.current, {
mode: 'javascript',
theme: 'material',
lineNumbers: true
});
editor.on('change', (instance, changeObj) => {
setCode(instance.getValue());
});
}, []);
The code comparison shows that React-CodeMirror2 provides a more React-friendly approach with a controlled component, while CodeMirror 5 requires manual setup and event handling within a useEffect hook.
Codemirror Component for React.js
Pros of react-codemirror
- More established and mature project with a longer history
- Better documentation and examples available
- Wider community support and adoption
Cons of react-codemirror
- Less frequent updates and maintenance
- Not optimized for the latest React versions
- Lacks some modern features and customization options
Code Comparison
react-codemirror:
import CodeMirror from 'react-codemirror';
<CodeMirror
value={this.state.code}
onChange={this.updateCode}
options={{
mode: 'javascript',
lineNumbers: true
}}
/>
react-codemirror2:
import { Controlled as CodeMirror } from 'react-codemirror2';
<CodeMirror
value={this.state.code}
onBeforeChange={(editor, data, value) => {
this.setState({ code: value });
}}
options={{
mode: 'javascript',
lineNumbers: true
}}
/>
The main difference in usage is that react-codemirror2 provides more granular control over the editor's state and events, while react-codemirror has a simpler API. react-codemirror2 also offers better performance and compatibility with modern React practices, such as controlled components.
React Ace Component
Pros of react-ace
- More comprehensive documentation and examples
- Wider range of supported languages and themes
- Active development and frequent updates
Cons of react-ace
- Larger bundle size due to additional features
- Steeper learning curve for advanced customizations
- May have performance issues with very large files
Code Comparison
react-ace:
import AceEditor from 'react-ace';
import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/theme-monokai';
<AceEditor
mode="javascript"
theme="monokai"
onChange={handleChange}
name="code-editor"
editorProps={{ $blockScrolling: true }}
/>
react-codemirror2:
import { Controlled as CodeMirror } from 'react-codemirror2';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/theme/monokai.css';
<CodeMirror
value={code}
options={{
mode: 'javascript',
theme: 'monokai',
}}
onBeforeChange={(editor, data, value) => {
setCode(value);
}}
/>
Both libraries offer React components for code editing, but react-ace provides more out-of-the-box features and language support. react-codemirror2 offers a more lightweight solution with potentially better performance for simpler use cases. The choice between the two depends on specific project requirements and preferences.
Monaco Editor for React.
Pros of react-monaco-editor
- More comprehensive language support and features, including IntelliSense and debugging capabilities
- Better performance for large files and complex syntax highlighting
- Seamless integration with TypeScript and JavaScript ecosystems
Cons of react-monaco-editor
- Larger bundle size, which may impact initial load times
- Steeper learning curve due to more complex API and configuration options
- Less flexibility for customization compared to CodeMirror
Code Comparison
react-monaco-editor:
import MonacoEditor from 'react-monaco-editor';
<MonacoEditor
width="800"
height="600"
language="javascript"
theme="vs-dark"
value={code}
onChange={handleEditorChange}
/>
react-codemirror2:
import { Controlled as CodeMirror } from 'react-codemirror2';
<CodeMirror
value={code}
options={{
mode: 'javascript',
theme: 'material',
lineNumbers: true
}}
onBeforeChange={(editor, data, value) => {
handleEditorChange(value);
}}
/>
Both libraries provide React components for code editing, but react-monaco-editor offers more advanced features at the cost of increased complexity and bundle size. react-codemirror2 is lighter and easier to set up, making it suitable for simpler use cases or projects with size constraints.
A browser based code editor
Pros of monaco-editor
- More feature-rich, offering advanced IDE-like capabilities
- Better performance for large files and complex syntax highlighting
- Extensive language support out-of-the-box
Cons of monaco-editor
- Larger bundle size, which may impact load times
- Steeper learning curve due to its complexity
- Less straightforward integration with React compared to react-codemirror2
Code Comparison
monaco-editor:
import * as monaco from 'monaco-editor';
const editor = monaco.editor.create(document.getElementById('container'), {
value: 'console.log("Hello, world!");',
language: 'javascript'
});
react-codemirror2:
import { Controlled as CodeMirror } from 'react-codemirror2';
<CodeMirror
value={code}
options={{
mode: 'javascript',
theme: 'material',
lineNumbers: true
}}
onBeforeChange={(editor, data, value) => {
setCode(value);
}}
/>
The code comparison shows that monaco-editor requires more setup but offers more control, while react-codemirror2 provides a more React-friendly integration with simpler props and callbacks.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
react-codemirror2
demo @ scniro.github.io/react-codemirror2
Install
npm install react-codemirror2 codemirror --save
react-codemirror2
ships with the notion of an uncontrolled and controlled component. UnControlled
consists of a simple wrapper largely powered by the inner workings of codemirror
itself, while Controlled
will demand state management from the user, preventing codemirror changes unless properly handled via value
. The latter will offer more control and likely be more appropriate with redux heavy apps.
uncontrolled usage
import {UnControlled as CodeMirror} from 'react-codemirror2'
<CodeMirror
value='<h1>I ⥠react-codemirror2</h1>'
options={{
mode: 'xml',
theme: 'material',
lineNumbers: true
}}
onChange={(editor, data, value) => {
}}
/>
controlled usage
import {Controlled as CodeMirror} from 'react-codemirror2'
<CodeMirror
value={this.state.value}
options={options}
onBeforeChange={(editor, data, value) => {
this.setState({value});
}}
onChange={(editor, data, value) => {
}}
/>
requiring codemirror resources
codemirror
comes as a peer dependency, meaning you'll need to require it in your project in addition to react-codemirror2
. This prevents any versioning conflicts that would arise if codemirror
came as a dependency through this wrapper. It's been observed that version mismatches can cause difficult to trace issues such as syntax highlighting disappearing without any explicit errors/warnings
- additional
Since codemirror ships mostly unconfigured, the user is left with the responsibility for requiring any additional resources should they be necessary. This is often the case when specifying certain language modes and themes. How to import/require these assets will vary according to the specifics of your development environment. Below is a sample to include the assets necessary to specify a mode of xml
(HTML) and a material
theme.
note that the base codemirror.css file is required in all use cases
@import 'codemirror/lib/codemirror.css';
@import 'codemirror/theme/material.css';
import CodeMirror from 'react-codemirror2';
require('codemirror/mode/xml/xml');
require('codemirror/mode/javascript/javascript');
props
prop | type default | components | description |
---|---|---|---|
autoCursor | boolean true | Controlled UnControlled | should component cursor position correct when value changed |
autoScroll | boolean true | Controlled UnControlled | should component scroll cursor position into view when value changed |
className | string | Controlled UnControlled | pass through class class="react-codemirror2 className" |
defineMode | object | Controlled UnControlled | pass a custom mode via {name: 'custom', fn: myModeFn} |
detach | boolean | UnControlled | should component ignore new props |
options | object | Controlled UnControlled | codemirror configuration |
value | string | *Controlled UnControlled | * component value must be managed for controlled components |
props cont. (wrapped codemirror programming api)
cursor
- setCursor
will programmatically set cursor to the position specified
<CodeMirror
[...]
cursor={{
line: 5,
ch: 10
}}
onCursor={(editor, data) => {}}
/>
scroll
- scrollTo
will programmatically scroll to the specified coordinate
<CodeMirror
[...]
scroll={{
x: 50,
y: 50
}}
onScroll={(editor, data) => {}}
/>
selection={{ranges: array<{anchor, head}>, focus?: boolean}
- setSelections
will programmatically select the ranges specified
<CodeMirror
[...]
selection={{
ranges: [{
anchor: {ch: 8, line: 5},
head: {ch: 37, line: 5}
}],
focus: true // defaults false if not specified
}}
onSelection={(editor, data) => {}}
/>
events
event | components | description |
---|---|---|
editorDidAttach(editor) | UnControlled | component is now responding to new props |
editorDidConfigure(editor) | Controlled UnControlled | component configuration has been set |
editorDidDetach(editor) | UnControlled | component is now ignoring new props |
editorDidMount(editor, [next]) | Controlled UnControlled | * invoking optional next will trigger editorDidConfigure |
editorWillUnmount(editor) | Controlled UnControlled | invoked before componentWillUnmount |
onBeforeChange(editor, data, value, [next]) | Controlled UnControlled | * if used, next is returned via UnControlled and must be invoked to trigger onChange |
onChange(editor, data, value) | Controlled UnControlled | the component value has been changed |
events cont. wrapped codemirror events
onBlur(editor, event)
- bluronContextMenu(editor, event)
- contextmenuonCopy(editor)
- copyonCursor(editor, data)
- cursorActivityonCursorActivity(editor)
- cursorActivityonCut(editor)
- cutonDblClick(editor, event)
- dblclickonDragEnter(editor, event)
- dragenteronDragOver(editor, event)
- dragoveronDragLeave(editor, event)
- dragleaveonDragStart(editor, event)
- dragstartonDrop(editor, event)
- droponFocus(editor, event)
- focusonGutterClick(editor, lineNumber, gutter, event)
- gutterClickonInputRead(editor, changeObj)
- gutterClickonKeyDown(editor, event)
- keydownonKeyHandled(editor, key, event)
- keyhandledonKeyPress(editor, event)
- keypressonKeyUp(editor, event)
- keyuponMouseDown(editor, event)
- mousedownonPaste(editor)
- pasteonScroll(editor, data)
- scrollonSelection(editor, data)
- beforeSelectionChangeonTouchStart(editor, event)
- touchstartonUpdate(editor, event)
- updateonViewportChange(editor, from, to)
- viewportChange
FAQ
- Is server side rendering supported?
Yes. react-codemirror2 will prevent rendering in absence of window
. You can also force the component to not render via a PREVENT_CODEMIRROR_RENDER
global.
- How can I get the instance?
The recommended technique to get the instance is to persist the editor
returned via event callbacks. There is no static method to get it on demand, e.g. CodeMirror.getInstance()
. Example...
constructor() {
this.instance = null;
}
render() {
<CodeMirror editorDidMount={editor => { this.instance = editor }}/>
}
- How can I have a resizable editor?
Check out bokuweb/re-resizable. Wrapping your component with <Resizable/>'s
works well
Contributing
Pull Requests are welcome. Be mindful of the available scripts below to help submitting a well-received contribution.
npm run start
to run the app onlocalhost:8000
npm run test
to ensure tests continue to passnpm run build
to generate the demo bundle
note that it's necessary to bump the package.json version prior to final npm run build
so we can grab the proposed new version as seen in the demo header. Also note, the core changes are to be made in src/index.tsx
as ./index.js
and ./index.d.ts
are generated
Top Related Projects
In-browser code editor (version 5, legacy)
Codemirror Component for React.js
React Ace Component
Monaco Editor for React.
A browser based code editor
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot