仕事でWebアプリにマークダウン的なエディタを組み込もうかと思って、いろいろ探していたんだけど、文字色とかも変えられるようにしたいなと思い、マークダウンだと足りないのでReactでエディタを1からつくろうかと思ったら、すでにdraft.jsというものがありました。しかもfacebook製ということで期待できます。
draft.jsはリッチなテキストエディタを簡単に作ることのできるReactで実装されたフレームワークです。
この記事は、draft.jsの公式ドキュメントをベースに、自分への備忘録含めて内容をかいつまんで和訳したものです。
公式ドキュメント: https://facebook.github.io/draft-js/
デモも含まれているので、どんなものかはこちらで試せます。
インストール
npmからインストールできます。
npm install --save draft-js react react-dom
使い方
Draft.jsはunicodeをサポートしているため、HTMLのheadタグにはいかのメタタグを必ず入れてください。
<meta charset="utf-8" />
import React from 'react';
import ReactDOM from 'react-dom';
import {Editor, EditorState} from 'draft-js';
class MyEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.onChange = (editorState) => this.setState({editorState});
}
render() {
const {editorState} = this.state;
return <Editor editorState={editorState} onChange={this.onChange} />;
}
}
ReactDOM.render(
<MyEditor />,
document.getElementById('container')
);
Editorコンポーネントは、HTML5のContentEditable属性を持つコンポーネントが作られます。Editorでの状態は「EditorState」ですべて表され、onChangeから取得することができます。
##EditorState
EditorStateは現在のEditorのStateのスナップショットであったり、コンテンツ、カーソル、undo/redoの履歴などをふくんでいます。内部で変更があるごとに新しいEditorStateは生成され、onChangeに設定したハンドラーから新しく生成されたEditorStateが取得することができます。
EditorStateに変更を加えたい場合には「RichUtils」が提供されています。似たようなものに「Modifier」もあります。こちらもテキストやスタイルを変更するための機能を適用するためのモジュールです。
RichUtilsとキーコマンド
RichUilsはCmd+B(ボールド)のようなキーコマンドの情報を持っています。EditorでhandleKeyCommandのpropでキーコマンドを内容を監視できるので、RichUtilsを通して内容をキーコマンドの内容を適用することができます。
import {Editor, EditorState, RichUtils} from 'draft-js';
class MyEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.onChange = (editorState) => this.setState({editorState});
this.handleKeyCommand = this.handleKeyCommand.bind(this);
}
handleKeyCommand(command) {
const newState = RichUtils.handleKeyCommand(this.state.editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
render() {
return (
<Editor
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
/>
);
}
}
UIボタン
キーコマンドからスタイルを変更するを上で紹介しましたが、ボタンを配置して押されたスタイルを変更させたい場合の例です。ボタンを押すとボールドになります。
class MyEditor extends React.Component {
// …
_onBoldClick() {
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
}
render() {
return (
<div>
<button onClick={this._onBoldClick.bind(this)}>Bold</button>
<Editor
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
/>
</div>
);
}
}