はじめに
「アプリにMarkdownエディタを組み込みたいけれど、テキストエリアとプレビューを並べただけの画面では使いにくい」——そんな悩みを抱えたことはありませんか?
エンジニアにとってMarkdownは慣れ親しんだ記法ですが、非エンジニアのユーザーにとっては「# や ** って何?」という世界です。かといって、リッチテキストエディタを自前で実装するのは膨大な工数がかかります。
そんな課題を解決してくれるのが、オープンソースのReactコンポーネント「MDXEditor」です。Google DocsやNotionのような直感的な編集体験を提供しながら、データはあくまでMarkdownとして保存できる、いいとこ取りのライブラリです。この記事では、MDXEditorの基本から実践的な使い方まで、コピペで動くコード例とともに解説します。
MDXEditorとは
MDXEditorは、Markdownドキュメントを「見たまま」編集できるReact製のWYSIWYGエディタコンポーネントです。WYSIWYG(What You See Is What You Get)とは、編集画面の見た目がそのまま最終的な表示になる方式のことで、プレビュー画面との切り替えが不要になります。
MITライセンスで公開されており、GitHubで3.6k以上のスターを獲得している人気プロジェクトです。2026年6月にはメジャーバージョンとなるv4系がリリースされ、活発に開発が続いています。
主な特徴
- 真のWYSIWYG編集 - 「編集画面」と「プレビュー画面」の分離がなく、Google DocsやNotionのように書いたそばから整形されます。非エンジニアでも迷わず使えます
- 出力はプレーンなMarkdown - エディタ上ではリッチに見えても、保存されるデータは標準的なMarkdown文字列です。既存のMarkdownベースのシステムにそのまま組み込めます
- プラグインアーキテクチャ - 見出し、リスト、テーブル、画像、コードブロックなどの機能がすべてプラグインとして分離されています。必要な機能だけを選んで軽量に保てます
- コードブロックの本格編集 - CodeMirrorを統合した編集可能なコードブロックに対応し、言語ごとのシンタックスハイライトも利用できます
- MDX(JSXコンポーネント)対応 - 名前の由来でもあるMDXをサポートし、Markdown中のReactコンポーネントも編集できます
インストール
npmやyarn、pnpmでインストールできます。
# npm
npm install --save @mdxeditor/editor
# yarn
yarn add @mdxeditor/editor
# pnpm
pnpm add @mdxeditor/editor
基本的な使い方
最小構成のエディタは、わずか数行で動きます。付属のCSSファイルのインポートを忘れないようにしましょう。
import { MDXEditor, headingsPlugin } from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function App() {
return <MDXEditor markdown="# Hello World" plugins={[headingsPlugin()]} />
}
これだけで、見出しをWYSIWYGで編集できるエディタが表示されます。
プラグインで機能を追加する
MDXEditorの真価はプラグインシステムにあります。よく使う機能をまとめて有効化してみましょう。
import {
MDXEditor,
headingsPlugin,
listsPlugin,
quotePlugin,
thematicBreakPlugin,
markdownShortcutPlugin,
} from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function Editor() {
return (
<MDXEditor
markdown="# ようこそ MDXEditor へ"
plugins={[
headingsPlugin(), // 見出し
listsPlugin(), // 箇条書き・番号付きリスト
quotePlugin(), // 引用
thematicBreakPlugin(), // 水平線
markdownShortcutPlugin() // 「# + スペース」などのMarkdownショートカット
]}
/>
)
}
markdownShortcutPlugin を入れると、# に続けてスペースを打つと見出しに変換されるなど、Markdownに慣れたユーザーの入力体験も損ないません。
ツールバーを表示する
非エンジニア向けには、ボタン操作できるツールバーが欠かせません。toolbarPlugin に表示したいコンポーネントを渡します。
import {
MDXEditor,
headingsPlugin,
listsPlugin,
quotePlugin,
toolbarPlugin,
UndoRedo,
BoldItalicUnderlineToggles,
BlockTypeSelect,
} from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function EditorWithToolbar() {
return (
<MDXEditor
markdown="ツールバー付きエディタです"
plugins={[
headingsPlugin(),
listsPlugin(),
quotePlugin(),
toolbarPlugin({
toolbarContents: () => (
<>
<UndoRedo />
<BoldItalicUnderlineToggles />
<BlockTypeSelect />
</>
),
}),
]}
/>
)
}
ツールバーの中身はReactコンポーネントとして自由に組み替えられるため、アプリの要件に合わせて必要なボタンだけを並べられます。
編集内容を取得する
フォームとして使う場合は、onChange で最新のMarkdown文字列を受け取れます。
import { useState } from 'react'
import { MDXEditor, headingsPlugin, listsPlugin } from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function EditorForm() {
const [markdown, setMarkdown] = useState('# 下書き')
return (
<div>
<MDXEditor
markdown={markdown}
onChange={setMarkdown}
plugins={[headingsPlugin(), listsPlugin()]}
/>
<p>現在の文字数: {markdown.length}</p>
</div>
)
}
状態として保持したMarkdownをそのままAPIに送信すれば、保存処理も簡単に実装できます。
実践的なユースケース
Next.js(App Router)に組み込む
MDXEditorはブラウザのAPIに依存しているため、サーバーサイドレンダリング(SSR)には対応していません。Next.jsで使う場合は next/dynamic を使い、クライアント側でのみ読み込むようにします。
まず、エディタ本体をクライアントコンポーネントとして切り出します。
// components/InitializedMDXEditor.tsx
'use client'
import {
MDXEditor,
headingsPlugin,
listsPlugin,
quotePlugin,
markdownShortcutPlugin,
type MDXEditorProps,
} from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function InitializedMDXEditor(props: MDXEditorProps) {
return (
<MDXEditor
plugins={[
headingsPlugin(),
listsPlugin(),
quotePlugin(),
markdownShortcutPlugin(),
]}
{...props}
/>
)
}
次に、dynamic で SSR を無効化して読み込みます。
// app/edit/page.tsx
'use client'
import dynamic from 'next/dynamic'
const Editor = dynamic(() => import('@/components/InitializedMDXEditor'), {
ssr: false,
loading: () => <p>エディタを読み込み中...</p>,
})
export default function EditPage() {
return <Editor markdown="# Next.jsで動くMDXEditor" />
}
公式が Next.js用のサンプルリポジトリ を公開しているので、詰まったときはそちらも参考になります。
ブログのCMS風エディタを作る
コードブロックや画像、テーブルまで扱えるフル機能のエディタも、プラグインを足すだけで構築できます。
import {
MDXEditor,
headingsPlugin,
listsPlugin,
quotePlugin,
linkPlugin,
linkDialogPlugin,
imagePlugin,
tablePlugin,
codeBlockPlugin,
codeMirrorPlugin,
markdownShortcutPlugin,
} from '@mdxeditor/editor'
import '@mdxeditor/editor/style.css'
export default function BlogEditor({
initialContent,
onSave,
}: {
initialContent: string
onSave: (markdown: string) => void
}) {
return (
<MDXEditor
markdown={initialContent}
onChange={onSave}
contentEditableClassName="prose max-w-none"
plugins={[
headingsPlugin(),
listsPlugin(),
quotePlugin(),
linkPlugin(),
linkDialogPlugin(), // リンク挿入ダイアログ
imagePlugin(), // 画像の挿入
tablePlugin(), // テーブルのGUI編集
codeBlockPlugin({ defaultCodeBlockLanguage: 'ts' }),
codeMirrorPlugin({
codeBlockLanguages: { ts: 'TypeScript', js: 'JavaScript', css: 'CSS' },
}),
markdownShortcutPlugin(),
]}
/>
)
}
contentEditableClassName に任意のCSSクラスを指定できるため、Tailwind CSSの prose クラス(@tailwindcss/typography)を当てれば、公開ページと同じ見た目で編集できます。テーブルはセル単位でGUI編集でき、コードブロック内ではCodeMirrorによる言語別ハイライトが効きます。
このように「編集体験はNotion風、保存データはMarkdown」という構成にしておけば、既存の静的サイトジェネレータやMarkdownベースのブログシステムと自然に連携できます。
まとめ
この記事では、React製WYSIWYG MarkdownエディタのMDXEditorについて解説しました。
- MDXEditorは編集画面とプレビューの分離をなくす、真のWYSIWYG体験を提供します
- 出力はプレーンなMarkdownなので、既存システムへの組み込みが容易です
- プラグインアーキテクチャにより、必要な機能だけを選んで軽量に構成できます
- SSRには非対応のため、Next.jsでは
dynamicのssr: falseで読み込みます
社内ツールのドキュメント編集、CMSの記事入稿画面、コメント欄のリッチ化など、「Markdownで保存したいけれど編集は快適にしたい」場面で幅広く活躍します。まずは基本プラグインだけの最小構成から試して、必要に応じてツールバーやテーブル編集を足していくのがおすすめです。公式サイトのライブデモでは全機能をブラウザ上で試せるので、ぜひ触ってみてください。