rod

rodemirror

React component for CodeMirror 6

Showing:

Popularity

Downloads/wk

890

GitHub Stars

7

Maintenance

Last Commit

3d ago

Contributors

4

Package

Dependencies

0

License

MIT

Type Definitions

Built-In

Tree-Shakeable

Yes?

Categories

Readme

rodemirror

React component for CodeMirror 6

semantic-release

Installation

npm i rodemirror @codemirror/state @codemirror/view

Usage

Use the CodeMirror component:

import CodeMirror from 'rodemirror'
import { basicSetup } from '@codemirror/basic-setup'
import { oneDark } from '@codemirror/theme-one-dark'
import { javascript } from '@codemirror/lang-javascript'
import { useMemo } from 'react'

const Editor = () => {
  const extensions = useMemo(() => [basicSetup, oneDark, javascript()], [])

  return <CodeMirror extensions={extensions} />
}

The useMemo is so that the extensions are not recreated each time, which would cause unnecessary editor transactions. You'll want to do the same with the selection prop.

Uncontrolled

Create an uncontrolled component for reading values.

import { useState } from 'react'
import type { Extension } from '@codemirror/state'

const Editor = () => {
  const extensions = useMemo<Extension[]>(
    () => [basicSetup, oneDark, javascript()],
    []
  )

  const defaultValue = "console.log('Hello world!')"
  // remove if you do not need the value
  const [value, setValue] = useState(defaultValue)

  return (
    <CodeMirror
      value={defaultValue}
      onUpdate={(v) => {
        if (v.docChanged) {
          setValue(v.state.doc.toString())
        }
      }}
      extensions={extensions}
    />
  )
}

Controlled

Create a controlled component for reading and writing values. Simply replace the defaultValue with the value in state (based off the uncontrolled example). This is not recommended as you will be overwriting the entire document on each input and the editor will become very slow. This also does not work with features such as autocomplete. If you must pass in a controlled value, you can separate the reading and writing values and only update when necessary.

const defaultValue = "console.log('Hello world!')"
const [value, setValue] = useState(defaultValue)

return (
  <CodeMirror
-   value={defaultValue}
+   value={value}
    onUpdate={(v) => {
      if (v.docChanged) {
        setValue(v.state.doc.toString())
      }
    }}
    extensions={extensions}
  />
)

EditorView and EditorState (Complex Use Cases)

Unless you are performing complex actions, you likely do not need this. You can use callbacks to keep EditorView and EditorState. You can keep the EditorView in a useState like so:

import type { EditorView } from '@codemirror/view'

const Editor = () => {
  const extensions = useMemo(() => [basicSetup, oneDark, javascript()], [])

  const [editorView, setEditorView] = useState<EditorView | null>(null)

  return (
    <CodeMirror
      extensions={extensions}
      onEditorViewChange={(editorView) => setEditorView(editorView)}
    />
  )
}

The same applies to EditorState, though it can also be accessed from EditorView.state.

Examples

See the examples for how the editor can be used.

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100