@uiw/react-codemirror vs react-ace vs react-simple-code-editor vs react-monaco-editor
React Code Editor Libraries Comparison
1 Year
@uiw/react-codemirrorreact-acereact-simple-code-editorreact-monaco-editorSimilar Packages:
What's React Code Editor Libraries?

React code editor libraries provide developers with pre-built components that facilitate the integration of code editing features into React applications. These libraries often come with syntax highlighting, code formatting, and other essential features that enhance the user experience for applications requiring code input or editing capabilities. They are designed to be customizable and extensible, allowing developers to tailor the editor to their specific needs while maintaining performance and usability.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
@uiw/react-codemirror802,7121,795773 kB15610 hours agoMIT
react-ace430,5704,1342.01 MB22521 days agoMIT
react-simple-code-editor275,3821,64769.7 kB478 months agoMIT
react-monaco-editor141,0593,93858.5 kB76a month agoMIT
Feature Comparison: @uiw/react-codemirror vs react-ace vs react-simple-code-editor vs react-monaco-editor

Customization

  • @uiw/react-codemirror:

    @uiw/react-codemirror offers extensive customization options through its API, allowing developers to modify themes, key bindings, and add various plugins to enhance functionality. This makes it suitable for applications that require tailored editing experiences.

  • react-ace:

    react-ace provides a variety of themes and language modes, enabling developers to customize the editor's appearance and behavior easily. It supports a wide range of programming languages, making it versatile for different use cases.

  • react-simple-code-editor:

    react-simple-code-editor is designed for simplicity and ease of use, offering basic customization options like font size and style. It is less feature-rich than others, making it ideal for straightforward applications.

  • react-monaco-editor:

    react-monaco-editor allows deep customization similar to Visual Studio Code, including themes, language support, and editor behaviors. Developers can leverage its API to create a highly personalized coding environment.

Performance

  • @uiw/react-codemirror:

    @uiw/react-codemirror is optimized for performance with a lightweight footprint, making it suitable for applications that require fast loading times and responsive interactions, even with large codebases.

  • react-ace:

    react-ace is built on the Ace editor, which is known for its efficient rendering and performance, handling large files and complex syntax highlighting without significant lag, making it a good choice for performance-sensitive applications.

  • react-simple-code-editor:

    react-simple-code-editor is lightweight and performs well for basic code editing tasks. However, it may not handle very large files as efficiently as more robust editors.

  • react-monaco-editor:

    react-monaco-editor is designed for high performance, offering features like lazy loading and efficient rendering of large files, making it ideal for applications that need to handle extensive codebases seamlessly.

Learning Curve

  • @uiw/react-codemirror:

    @uiw/react-codemirror has a moderate learning curve due to its extensive features and customization options. Developers familiar with CodeMirror will find it easier to integrate and customize.

  • react-ace:

    react-ace is relatively easy to learn, especially for those who have experience with Ace. Its straightforward API allows for quick implementation and customization, making it accessible for beginners.

  • react-simple-code-editor:

    react-simple-code-editor has a very low learning curve, making it easy for beginners to implement basic code editing functionality without extensive setup.

  • react-monaco-editor:

    react-monaco-editor may have a steeper learning curve due to its advanced features and API. However, developers familiar with Visual Studio Code will find it intuitive to use and customize.

Feature Set

  • @uiw/react-codemirror:

    @uiw/react-codemirror supports a wide range of features, including syntax highlighting, linting, and customizable key bindings, making it suitable for complex applications that require advanced editing capabilities.

  • react-ace:

    react-ace offers a rich feature set, including code folding, autocomplete, and error highlighting, making it ideal for applications that need comprehensive code editing functionality.

  • react-simple-code-editor:

    react-simple-code-editor offers basic features like syntax highlighting and line numbering, making it suitable for simple applications that do not require extensive code editing capabilities.

  • react-monaco-editor:

    react-monaco-editor provides a feature-rich environment similar to Visual Studio Code, including IntelliSense, debugging support, and advanced code navigation, making it perfect for professional-grade applications.

Community and Support

  • @uiw/react-codemirror:

    @uiw/react-codemirror benefits from a strong community around CodeMirror, providing ample resources, plugins, and support for developers looking to extend its functionality.

  • react-ace:

    react-ace has a large user base and community support, with numerous tutorials and resources available, making it easier for developers to find help and examples.

  • react-simple-code-editor:

    react-simple-code-editor has a smaller community compared to others, but it is straightforward to use, and basic support is available through its documentation.

  • react-monaco-editor:

    react-monaco-editor is backed by the Visual Studio Code community, ensuring robust support and a wealth of resources for troubleshooting and feature enhancements.

How to Choose: @uiw/react-codemirror vs react-ace vs react-simple-code-editor vs react-monaco-editor
  • @uiw/react-codemirror:

    Choose @uiw/react-codemirror if you need a lightweight and flexible editor that supports multiple programming languages and offers a rich plugin ecosystem. It is ideal for projects where you want to customize the editor extensively and require features like linting and code folding.

  • react-ace:

    Select react-ace if you are looking for a robust editor that provides a wide range of themes and modes, making it suitable for applications that need to support various languages. It is built on the Ace editor, which is known for its performance and extensive features, including code completion and error highlighting.

  • react-simple-code-editor:

    Use react-simple-code-editor for a minimalistic approach when you need a lightweight and easy-to-use code editor. It is best suited for projects that require basic code editing features without the overhead of more complex editors.

  • react-monaco-editor:

    Opt for react-monaco-editor if you want a powerful editor that closely resembles Visual Studio Code. It provides advanced features like IntelliSense, code navigation, and debugging capabilities, making it perfect for applications that require a professional-grade code editing experience.

README for @uiw/react-codemirror

react-codemirror logo

react-codemirror

Buy me a coffee NPM Downloads Build & Deploy Open in unpkg npm version Coverage Status Open in Gitpod

CodeMirror component for React. Demo Preview: @uiwjs.github.io/react-codemirror

Features:

🚀 Quickly and easily configure the API.
🌱 Versions after @uiw/react-codemirror@v4 use codemirror 6. #88.
⚛️ Support the features of React Hook(requires React 16.8+).
📚 Use Typescript to write, better code hints.
🌐 The bundled version supports use directly in the browser #267.
🌎 There are better sample previews.
🎨 Support theme customization, provide theme editor.

Install

Not dependent on uiw.

npm install @uiw/react-codemirror --save

All Packages

| Name | NPM Version | | :-------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | @uiw/react-codemirror | npm version NPM Downloads | | react-codemirror-merge | npm version NPM Downloads | | @uiw/codemirror-extensions-basic-setup | npm version NPM Downloads | | @uiw/codemirror-extensions-color | npm version NPM Downloads | | @uiw/codemirror-extensions-classname | npm version NPM Downloads | | @uiw/codemirror-extensions-events | npm version NPM Downloads | | @uiw/codemirror-extensions-hyper-link | npm version NPM Downloads | | @uiw/codemirror-extensions-langs | npm version NPM Downloads | | @uiw/codemirror-extensions-line-numbers-relative | npm version NPM Downloads | | @uiw/codemirror-extensions-mentions | npm version NPM Downloads | | @uiw/codemirror-extensions-zebra-stripes | npm version NPM Downloads | | @uiw/codemirror-themes | npm version NPM Downloads |

| Name | NPM Version | | :----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | @uiw/codemirror-themes-all | npm version NPM Downloads | | @uiw/codemirror-theme-abcdef | npm version NPM Downloads | | @uiw/codemirror-theme-abyss | npm version NPM Downloads | | @uiw/codemirror-theme-androidstudio | npm version NPM Downloads | | @uiw/codemirror-theme-andromeda | npm version NPM Downloads | | @uiw/codemirror-theme-atomone | npm version NPM Downloads | | @uiw/codemirror-theme-aura | npm version NPM Downloads | | @uiw/codemirror-theme-basic | npm version NPM Downloads | | @uiw/codemirror-theme-bbedit | npm version NPM Downloads | | @uiw/codemirror-theme-bespin | npm version NPM Downloads | | @uiw/codemirror-theme-console | npm version NPM Downloads | | @uiw/codemirror-theme-copilot | npm version NPM Downloads | | @uiw/codemirror-theme-duotone | npm version NPM Downloads | | @uiw/codemirror-theme-dracula | npm version NPM Downloads | | @uiw/codemirror-theme-darcula | npm version NPM Downloads | | @uiw/codemirror-theme-eclipse | npm version NPM Downloads | | @uiw/codemirror-theme-github | npm version NPM Downloads | | @uiw/codemirror-theme-gruvbox-dark | npm version NPM Downloads | | @uiw/codemirror-theme-kimbie | npm version NPM Downloads | | @uiw/codemirror-theme-kimbie | npm version NPM Downloads | | @uiw/codemirror-theme-material | npm version NPM Downloads | | @uiw/codemirror-theme-monokai | npm version NPM Downloads | | @uiw/codemirror-theme-noctis-lilac | npm version NPM Downloads | | @uiw/codemirror-theme-nord | npm version NPM Downloads | | @uiw/codemirror-theme-okaidia | npm version NPM Downloads | | @uiw/codemirror-theme-quietlight | npm version NPM Downloads | | @uiw/codemirror-theme-red | npm version NPM Downloads | | @uiw/codemirror-theme-solarized | npm version NPM Downloads | | @uiw/codemirror-theme-sublime | npm version NPM Downloads | | @uiw/codemirror-theme-tokyo-night | npm version NPM Downloads | | @uiw/codemirror-theme-tokyo-night-storm | npm version NPM Downloads | | @uiw/codemirror-theme-tokyo-night-day | npm version NPM Downloads | | @uiw/codemirror-theme-vscode | npm version NPM Downloads | | @uiw/codemirror-theme-white | npm version NPM Downloads | | @uiw/codemirror-theme-tomorrow-night-blue | npm version NPM Downloads | | @uiw/codemirror-theme-xcode | npm version NPM Downloads |

Usage

Open in CodeSandbox

import React from 'react';
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

function App() {
  const [value, setValue] = React.useState("console.log('hello world!');");
  const onChange = React.useCallback((val, viewUpdate) => {
    console.log('val:', val);
    setValue(val);
  }, []);
  return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
}
export default App;

Support Language

Open in CodeSandbox

import CodeMirror from '@uiw/react-codemirror';
import { StreamLanguage } from '@codemirror/language';
import { go } from '@codemirror/legacy-modes/mode/go';

const goLang = `package main
import "fmt"

func main() {
  fmt.Println("Hello, 世界")
}`;

export default function App() {
  return <CodeMirror value={goLang} height="200px" extensions={[StreamLanguage.define(go)]} />;
}

Markdown Example

Markdown language code is automatically highlighted.

Open in CodeSandbox

import CodeMirror from '@uiw/react-codemirror';
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
import { languages } from '@codemirror/language-data';

const code = `## Title

\`\`\`jsx
function Demo() {
  return <div>demo</div>
}
\`\`\`

\`\`\`bash
# Not dependent on uiw.
npm install @codemirror/lang-markdown --save
npm install @codemirror/language-data --save
\`\`\`

[weisit ulr](https://uiwjs.github.io/react-codemirror/)

\`\`\`go
package main
import "fmt"
func main() {
  fmt.Println("Hello, 世界")
}
\`\`\`
`;

export default function App() {
  return <CodeMirror value={code} extensions={[markdown({ base: markdownLanguage, codeLanguages: languages })]} />;
}

Codemirror Merge

A component that highlights the changes between two versions of a file in a side-by-side view, highlighting added, modified, or deleted lines of code.

npm install react-codemirror-merge  --save
import CodeMirrorMerge from 'react-codemirror-merge';
import { EditorView } from 'codemirror';
import { EditorState } from '@codemirror/state';

const Original = CodeMirrorMerge.Original;
const Modified = CodeMirrorMerge.Modified;
let doc = `one
two
three
four
five`;

export const Example = () => {
  return (
    <CodeMirrorMerge>
      <Original value={doc} />
      <Modified
        value={doc.replace(/t/g, 'T') + 'Six'}
        extensions={[EditorView.editable.of(false), EditorState.readOnly.of(true)]}
      />
    </CodeMirrorMerge>
  );
};

Support Hook

Open in CodeSandbox

import { useEffect, useMemo, useRef } from 'react';
import { useCodeMirror } from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';

const code = "console.log('hello world!');\n\n\n";
// Define the extensions outside the component for the best performance.
// If you need dynamic extensions, use React.useMemo to minimize reference changes
// which cause costly re-renders.
const extensions = [javascript()];

export default function App() {
  const editor = useRef();
  const { setContainer } = useCodeMirror({
    container: editor.current,
    extensions,
    value: code,
  });

  useEffect(() => {
    if (editor.current) {
      setContainer(editor.current);
    }
  }, [editor.current]);

  return <div ref={editor} />;
}

Using Theme

We have created a theme editor where you can define your own theme. We have also defined some themes ourselves, which can be installed and used directly. Below is a usage example:

import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { okaidia } from '@uiw/codemirror-theme-okaidia';

const extensions = [javascript({ jsx: true })];

export default function App() {
  return <CodeMirror value="console.log('hello world!');" height="200px" theme={okaidia} extensions={extensions} />;
}

Using custom theme

import CodeMirror from '@uiw/react-codemirror';
import { createTheme } from '@uiw/codemirror-themes';
import { javascript } from '@codemirror/lang-javascript';
import { tags as t } from '@lezer/highlight';

const myTheme = createTheme({
  theme: 'light',
  settings: {
    background: '#ffffff',
    backgroundImage: '',
    foreground: '#75baff',
    caret: '#5d00ff',
    selection: '#036dd626',
    selectionMatch: '#036dd626',
    lineHighlight: '#8a91991a',
    gutterBackground: '#fff',
    gutterForeground: '#8a919966',
  },
  styles: [
    { tag: t.comment, color: '#787b8099' },
    { tag: t.variableName, color: '#0080ff' },
    { tag: [t.string, t.special(t.brace)], color: '#5c6166' },
    { tag: t.number, color: '#5c6166' },
    { tag: t.bool, color: '#5c6166' },
    { tag: t.null, color: '#5c6166' },
    { tag: t.keyword, color: '#5c6166' },
    { tag: t.operator, color: '#5c6166' },
    { tag: t.className, color: '#5c6166' },
    { tag: t.definition(t.typeName), color: '#5c6166' },
    { tag: t.typeName, color: '#5c6166' },
    { tag: t.angleBracket, color: '#5c6166' },
    { tag: t.tagName, color: '#5c6166' },
    { tag: t.attributeName, color: '#5c6166' },
  ],
});
const extensions = [javascript({ jsx: true })];

export default function App() {
  const onChange = React.useCallback((value, viewUpdate) => {
    console.log('value:', value);
  }, []);
  return (
    <CodeMirror
      value="console.log('hello world!');"
      height="200px"
      theme={myTheme}
      extensions={extensions}
      onChange={onChange}
    />
  );
}

Use initialState to restore state from JSON-serialized representation

CodeMirror allows to serialize editor state to JSON representation with toJSON function for persistency or other needs. This JSON representation can be later used to recreate ReactCodeMirror component with the same internal state.

For example, this is how undo history can be saved in the local storage, so that it remains after the page reloads

import CodeMirror from '@uiw/react-codemirror';
import { historyField } from '@codemirror/commands';

// When custom fields should be serialized, you can pass them in as an object mapping property names to fields.
// See [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) documentation for more details
const stateFields = { history: historyField };

export function EditorWithInitialState() {
  const serializedState = localStorage.getItem('myEditorState');
  const value = localStorage.getItem('myValue') || '';

  return (
    <CodeMirror
      value={value}
      initialState={
        serializedState
          ? {
              json: JSON.parse(serializedState || ''),
              fields: stateFields,
            }
          : undefined
      }
      onChange={(value, viewUpdate) => {
        localStorage.setItem('myValue', value);

        const state = viewUpdate.state.toJSON(stateFields);
        localStorage.setItem('myEditorState', JSON.stringify(state));
      }}
    />
  );
}

Props

  • value?: string value of the auto created model in the editor.
  • width?: string width of editor. Defaults to auto.
  • height?: string height of editor. Defaults to auto.
  • theme?: 'light' / 'dark' / Extension Defaults to 'light'.
import React from 'react';
import { EditorState, EditorStateConfig, Extension } from '@codemirror/state';
import { EditorView, ViewUpdate } from '@codemirror/view';
export * from '@codemirror/view';
export * from '@codemirror/basic-setup';
export * from '@codemirror/state';
export interface UseCodeMirror extends ReactCodeMirrorProps {
  container?: HTMLDivElement | null;
}
export declare function useCodeMirror(props: UseCodeMirror): {
  state: EditorState | undefined;
  setState: import('react').Dispatch<import('react').SetStateAction<EditorState | undefined>>;
  view: EditorView | undefined;
  setView: import('react').Dispatch<import('react').SetStateAction<EditorView | undefined>>;
  container: HTMLDivElement | null | undefined;
  setContainer: import('react').Dispatch<import('react').SetStateAction<HTMLDivElement | null | undefined>>;
};
export interface ReactCodeMirrorProps
  extends Omit<EditorStateConfig, 'doc' | 'extensions'>,
    Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'placeholder'> {
  /** value of the auto created model in the editor. */
  value?: string;
  height?: string;
  minHeight?: string;
  maxHeight?: string;
  width?: string;
  minWidth?: string;
  maxWidth?: string;
  /** focus on the editor. */
  autoFocus?: boolean;
  /** Enables a placeholder—a piece of example content to show when the editor is empty. */
  placeholder?: string | HTMLElement;
  /**
   * `light` / `dark` / `Extension` Defaults to `light`.
   * @default light
   */
  theme?: 'light' | 'dark' | Extension;
  /**
   * Whether to optional basicSetup by default
   * @default true
   */
  basicSetup?: boolean | BasicSetupOptions;
  /**
   * This disables editing of the editor content by the user.
   * @default true
   */
  editable?: boolean;
  /**
   * This disables editing of the editor content by the user.
   * @default false
   */
  readOnly?: boolean;
  /**
   * Controls whether pressing the `Tab` key inserts a tab character and indents the text (`true`)
   * or behaves according to the browser's default behavior (`false`).
   * @default true
   */
  indentWithTab?: boolean;
  /** Fired whenever a change occurs to the document. */
  onChange?(value: string, viewUpdate: ViewUpdate): void;
  /** Some data on the statistics editor. */
  onStatistics?(data: Statistics): void;
  /** The first time the editor executes the event. */
  onCreateEditor?(view: EditorView, state: EditorState): void;
  /** Fired whenever any state change occurs within the editor, including non-document changes like lint results. */
  onUpdate?(viewUpdate: ViewUpdate): void;
  /**
   * Extension values can be [provided](https://codemirror.net/6/docs/ref/#state.EditorStateConfig.extensions) when creating a state to attach various kinds of configuration and behavior information.
   * They can either be built-in extension-providing objects,
   * such as [state fields](https://codemirror.net/6/docs/ref/#state.StateField) or [facet providers](https://codemirror.net/6/docs/ref/#state.Facet.of),
   * or objects with an extension in its `extension` property. Extensions can be nested in arrays arbitrarily deep—they will be flattened when processed.
   */
  extensions?: Extension[];
  /**
   * If the view is going to be mounted in a shadow root or document other than the one held by the global variable document (the default), you should pass it here.
   * Originally from the [config of EditorView](https://codemirror.net/6/docs/ref/#view.EditorView.constructor%5Econfig.root)
   */
  root?: ShadowRoot | Document;
  /**
   * Create a state from its JSON representation serialized with [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) function
   */
  initialState?: {
    json: any;
    fields?: Record<'string', StateField<any>>;
  };
}
export interface ReactCodeMirrorRef {
  editor?: HTMLDivElement | null;
  state?: EditorState;
  view?: EditorView;
}
declare const ReactCodeMirror: React.ForwardRefExoticComponent<
  ReactCodeMirrorProps & React.RefAttributes<ReactCodeMirrorRef>
>;
export default ReactCodeMirror;
export interface BasicSetupOptions {
  lineNumbers?: boolean;
  highlightActiveLineGutter?: boolean;
  highlightSpecialChars?: boolean;
  history?: boolean;
  foldGutter?: boolean;
  drawSelection?: boolean;
  dropCursor?: boolean;
  allowMultipleSelections?: boolean;
  indentOnInput?: boolean;
  syntaxHighlighting?: boolean;
  bracketMatching?: boolean;
  closeBrackets?: boolean;
  autocompletion?: boolean;
  rectangularSelection?: boolean;
  crosshairCursor?: boolean;
  highlightActiveLine?: boolean;
  highlightSelectionMatches?: boolean;
  closeBracketsKeymap?: boolean;
  defaultKeymap?: boolean;
  searchKeymap?: boolean;
  historyKeymap?: boolean;
  foldKeymap?: boolean;
  completionKeymap?: boolean;
  lintKeymap?: boolean;
}
import { EditorSelection, SelectionRange } from '@codemirror/state';
import { ViewUpdate } from '@codemirror/view';
export interface Statistics {
  /** Get the number of lines in the editor. */
  lineCount: number;
  /** total length of the document */
  length: number;
  /** Get the proper [line-break](https://codemirror.net/docs/ref/#state.EditorState^lineSeparator) string for this state. */
  lineBreak: string;
  /** Returns true when the editor is [configured](https://codemirror.net/6/docs/ref/#state.EditorState^readOnly) to be read-only. */
  readOnly: boolean;
  /** The size (in columns) of a tab in the document, determined by the [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) facet. */
  tabSize: number;
  /** Cursor Position */
  selection: EditorSelection;
  /** Make sure the selection only has one range. */
  selectionAsSingle: SelectionRange;
  /** Retrieves a list of all current selections. */
  ranges: readonly SelectionRange[];
  /** Get the currently selected code. */
  selectionCode: string;
  /**
   * The length of the given array should be the same as the number of active selections.
   * Replaces the content of the selections with the strings in the array.
   */
  selections: string[];
  /** Return true if any text is selected. */
  selectedText: boolean;
}
export declare const getStatistics: (view: ViewUpdate) => Statistics;

Development

  1. Install dependencies
$ npm install       # Installation dependencies
$ npm run build     # Compile all package
  1. Development @uiw/react-codemirror package:
$ cd core
# listen to the component compile and output the .js file
# listen for compilation output type .d.ts file
$ npm run watch # Monitor the compiled package `@uiw/react-codemirror`
  1. Launch documentation site
npm run start

Related

Contributors

As always, thanks to our amazing contributors!

Made with contributors.

License

Licensed under the MIT License.