React Simplemde Editor

React wrapper for simplemde (easymde) markdown editor
Alternatives To React Simplemde Editor
Project NameStarsDownloadsRepos Using ThisPackages Using ThisMost Recent CommitTotal ReleasesLatest ReleaseOpen IssuesLicenseLanguage
Mermaid58,00250531718 hours ago140September 13, 2022867mitJavaScript
Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
25 days ago1January 17, 20221,033mitJavaScript
📝A simple and elegant markdown editor, available for Linux, macOS and Windows.
Stackedit20,362215 days ago67March 29, 2021667apache-2.0JavaScript
In-browser Markdown editor
16 hours ago209mpl-2.0TypeScript
There can be more than Notion and Miro. AFFiNE is a next-gen knowledge base that brings planning, sorting and creating all together. Privacy first, open-source, customizable and ready to use.
Tui.editor15,9842661473 days ago38December 12, 2019487mitTypeScript
🍞📝 Markdown WYSIWYG Editor. GFM Standard + Chart & UML Extensible.
Editor.md12,95235816 days ago1June 27, 2015555mitJavaScript
The open source embeddable online markdown editor (component).
3 months ago516otherJavaScript
Not Just A Notepad! (golang + mongodb)
24 days ago568lgpl-3.0C++
A pleasant note-taking platform.
Tinacms8,831561a day ago105September 21, 202285otherTypeScript
The Markdown CMS
Simplemde Markdown Editor8,7281,5162012 years ago13June 14, 2016278mitJavaScript
A simple, beautiful, and embeddable JavaScript Markdown editor. Delightful editing for beginners and experts alike. Features built-in autosaving and spell checking.
Alternatives To React Simplemde Editor
Select To Compare

Alternative Project Comparisons

React SimpleMDE (EasyMDE) Markdown Editor

NPM version

React component wrapper for EasyMDE (the most fresh SimpleMDE fork).

Only two dependencies, React (peer) and EasyMDE (peer).

Built by @RIP21 👨‍💻

Table of contents generated with markdown-toc

New in v5

  • [breaking] Full rewrite to hooks. Means more reactive so, probably, less bugs related with updates. Minimum React version required >=16.8.2
  • [breaking] easymde now a peer dependency, please install it manually
  • [breaking] label prop has been removed
  • [breaking] SSR safe nets removed, please make sure to import it dynamically
  • [breaking] options shall be memoized to prevent new instances from being created on each render and other related to that bugs (more on that below)
  • [potentially-breaking] Forwards ref, so you can easily get access to div wrapper by using ref prop.
  • [potentially-breaking] Lots of bugs fixed, examples updated
  • [potentially-breaking] @babel/runtime helpers are no longer inlined but imported.


npm install --save react-simplemde-editor easymde

Note: Possibly you may need to install @babel/runtime, try without it, but if you don't have any issues, then you shouldn't.


Hosted demo

or to see it locally:

git clone
cd react-simplemde-editor
yarn install
yarn demo
open browser at localhost:3000


View the demo code for more examples.

All examples below are in TypeScript

Uncontrolled usage

import React from "react";
import SimpleMDE from "react-simplemde-editor";
import "easymde/dist/easymde.min.css";

<SimpleMDE />;

Controlled usage

export const ControlledUsage = () => {
  const [value, setValue] = useState("Initial value");

  const onChange = useCallback((value: string) => {
  }, []);

  return <SimpleMdeReact value={value} onChange={onChange} />;


You can set API of SimpleMDE options which you pass down as a options prop. If you're using TypeScript it will be inferred by compiler.

Note: if you don't specify a custom id it will automatically generate an id for you.

Note that you need to useMemo to memoize options so they do not change on each rerender! It will affect behavior and performance because then on each render of the parent that renders SimpleMdeReact you'll get a new instance of the editor, which you definitely want to avoid! Also, if you change options on each value change you will lose focus. So, put options as a const outside of the component, or if options shall be partially or fully set by props make sure to useMemo in case of functional/hooks components, or class field for class based components. Slightly more on that here: #164

export const UsingOptions = () => {
  const [value, setValue] = useState("Initial");

  const onChange = useCallback((value: string) => {
  }, []);

  const autofocusNoSpellcheckerOptions = useMemo(() => {
    return {
      autofocus: true,
      spellChecker: false,
    } as SimpleMDE.Options;
  }, []);

  return (


You can include key maps using the extraKeys prop. Read more at CodeMirror extra keys

export const UpdateableByHotKeys = () => {
  const extraKeys = useMemo<KeyMap>(() => {
    return {
      Up: function (cm) {
        cm.replaceSelection(" surprise. ");
      Down: function (cm) {
        cm.replaceSelection(" surprise again! ");
  }, []);

  const [value, setValue] = useState("initial");
  const onChange = (value: string) => setValue(value);

  return (
    <SimpleMdeReact value={value} onChange={onChange} extraKeys={extraKeys} />

Custom preview rendering example

import ReactDOMServer from "react-dom/server";

export const CustomPreview = () => {
  const customRendererOptions = useMemo(() => {
    return {
      previewRender() {
        return ReactDOMServer.renderToString(
              CodeBlock: CodeRenderer,
              Code: CodeRenderer,
    } as SimpleMDE.Options;
  }, []);

  return (
      <h4>Custom preview</h4>
      <SimpleMdeReact options={customRendererOptions} />

Events / Additional event listeners for events of CodeMirror

See full list of events here

import { SimpleMdeReact } from "react-simplemde-editor";
import type { SimpleMdeToCodemirrorEvents } from "react-simplemde-editor";

export const CustomEventListeners = () => {
  const [value, setValue] = useState("Initial value");

  const onChange = useCallback((value: string) => {
  }, []);

  // Make sure to always `useMemo` all the `options` and `events` props to ensure best performance!
  const events = useMemo(() => {
    return {
      focus: () => console.log(value),
    } as SimpleMdeToCodemirrorEvents;
  }, []);

  return <SimpleMdeReact events={events} value={value} onChange={onChange} />;


export const Autosaving = () => {
  const delay = 1000;
  const autosavedValue = localStorage.getItem(`smde_demo`) || "Initial value";
  const anOptions = useMemo(() => {
    return {
      autosave: {
        enabled: true,
        uniqueId: "demo",
  }, [delay]);

  return (
    <SimpleMdeReact id="demo" value={autosavedValue} options={anOptions} />

Retrieve easymde, codemirror or cursor info to be able to manipulate it.

export const GetDifferentInstances = () => {
  // simple mde
  const [simpleMdeInstance, setMdeInstance] = useState<SimpleMDE | null>(null);

  const getMdeInstanceCallback = useCallback((simpleMde: SimpleMDE) => {
  }, []);

  useEffect(() => {
    simpleMdeInstance &&"Hey I'm editor instance!", simpleMdeInstance);
  }, [simpleMdeInstance]);

  // codemirror
  const [codemirrorInstance, setCodemirrorInstance] = useState<Editor | null>(
  const getCmInstanceCallback = useCallback((editor: Editor) => {
  }, []);

  useEffect(() => {
    codemirrorInstance &&"Hey I'm codemirror instance!", codemirrorInstance);
  }, [codemirrorInstance]);

  // line and cursor
  const [lineAndCursor, setLineAndCursor] = useState<Position | null>(null);

  const getLineAndCursorCallback = useCallback((position: Position) => {
  }, []);

  useEffect(() => {
    lineAndCursor &&"Hey I'm line and cursor info!", lineAndCursor);
  }, [lineAndCursor]);

  return (
      <h4>Getting instance of Mde and codemirror and line and cursor info</h4>
        value="Go to console to see stuff logged"

Basic testing

Here is how you do it. It requires mock of certain browser pieces to work, but this is whole example.

import { act, render, screen } from "@testing-library/react";
import { useState } from "react";
import { SimpleMdeReact } from "react-simplemde-editor";
import userEvent from "@testing-library/user-event";

// @ts-ignore
Document.prototype.createRange = function () {
  return {
    setEnd: function () {},
    setStart: function () {},
    getBoundingClientRect: function () {
      return { right: 0 };
    getClientRects: function () {
      return {
        length: 0,
        left: 0,
        right: 0,

const Editor = () => {
  const [value, setValue] = useState("");
  return <SimpleMdeReact value={value} onChange={setValue} />;

describe("Renders", () => {
  it("succesfully", async () => {
    act(() => {
      render(<Editor />);
    const editor = await screen.findByRole("textbox");
    userEvent.type(editor, "hello");



export interface SimpleMDEReactProps
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
  id?: string;
  onChange?: (value: string, changeObject?: EditorChange) => void;
  value?: string;
  extraKeys?: KeyMap;
  options?: SimpleMDE.Options;
  events?: SimpleMdeToCodemirrorEvents;
  getMdeInstance?: GetMdeInstance;
  getCodemirrorInstance?: GetCodemirrorInstance;
  getLineAndCursor?: GetLineAndCursor;
  placeholder?: string;
  textareaProps?: Omit<
    "id" | "style" | "placeholder"

All exports list

default - SimpleMdeReact

SimpleMdeReact - same as default but named


SimpleMdeReactProps - props of the component

DOMEvent - certain events that are used to get events exported below

CopyEvents - only copy codemirror events

GlobalEvents - some other global codemirror events

DefaultEvent - default codemirror event handler function

IndexEventsSignature - index signature that expects string as key and returns DefaultEvent

SimpleMdeToCodemirrorEvents - manually crafted events (based off @types/[email protected] that easymde uses internally) + all the above merged together into whole mapping between Codemirror event names and actual handlers for events prop

GetMdeInstance - signature of the callback function that retrieves mde instance

GetCodemirrorInstance - signature of the callback function that retrieves codemirror instance

GetLineAndCursor - signature of the callback function that retrieves line and cursor info


New in v4

  • Now uses EasyMDE (the most fresh SimpleMDE fork) instead of simplemde itself. Possible breaking changes, so I bumped version to v4.
  • One obvious breaking change. Is how CSS is have to be imported. It used to be simplemde/dist/simplemde.min.css now it will be easymde/dist/easymde.min.css

New in v3

  • The initialValue prop has been removed and replaced with a value prop, allowing direct changes to the value to be made after the component mounts.
  • v3.6.8 if rendering server-side, you can set static ids to avoid errors in rendering synchronization.
  • v3.6.17 TypeScript typings added.
  • v3.6.19 All props will be passed to the wrapper now (except a id, onChange and few others that are ignored)
  • v3.6.21 React 17 support (UNSAFE methods are no longer used)

New in v2

Version 1.0 did not have SimpleMDE options configured well, this readme reflects the changes made to better include options. This is still a very new project. Testing, feedback and PRs are welcome and appreciated.

Popular Editor Projects
Popular Markdown Projects
Popular Text Editors Categories
Related Searches

Get A Weekly Email With Trending Projects For These Categories
No Spam. Unsubscribe easily at any time.
Markdown Editor