React Hook Form を使えばフォーム周りの state を一元管理したり、バリデーションを加えたり拡張できるけれど、Draft.js の値も組み込めるのか、というのが気になるところだと思う。
「React Hook Form で、Draft.js の state を管理したい」「React Hook Form と Draft.js を組み合わせたい」など、お困りなら力になれるかもしれない。
はじめに
リッチテキストエディタを単一に配置する程度ならば、個別に state を設けるのみで済まされる。これは Draft.js 公式のドキュメントに掲載されているように、ひとつの <Editor>
に対して、ひとつの editorState
を設定するというものだ。
だけど実際には、リッチテキストエディタもフォームの一部であることが自然で、そこには入力フィールドがあったり、選択フィールドがあったり、チェックボックスがあったりすることだろう。
そうするとフォームヘルパー系のライブラリ(react-hook-form
)によるフォーム管理が見込めるわけで、そんななか Draft.js の <Editor>
だけ別途 state を定義しているのは残念に思えてくる。
どうかこれも一緒に管理できないものか、というのがこのエントリーの根幹になっている。興味を引く内容であったならば引き続きお付き合いいただきたい。
React Hook Form と Draft.js を組み合わせよう
React Hook Form と Draft.js の組み合わせにおける最小構成を用意させてもらった。
実装環境
各種関連パッケージのバージョンは、以下コードを確認してほしい。
"dependencies": {
"draft-js": "^0.11.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.20.5"
...
},
コンポーネント
React コンポーネントは、以下コードを確認してほしい。
import { useState } from 'react';
import { useForm, useController } from 'react-hook-form';
import { Editor, EditorState, convertToRaw } from 'draft-js';
function App() {
const [raw, setRaw] = useState();
const { handleSubmit, control } = useForm();
const {
field: { onChange, value },
} = useController({
name: 'richEditor',
control,
rules: { required: true },
defaultValue: EditorState.createEmpty(),
});
const submit = ({ richEditor }) => {
const convertToRawData = convertToRaw(richEditor.getCurrentContent());
setRaw(convertToRawData);
};
return (
<form onSubmit={handleSubmit(submit)}>
<Editor editorState={value} onChange={onChange} />
<button type="submit">送信</button>
<pre>{JSON.stringify(raw, null, 2)}</pre>
</form>
);
}
export default App;
リッチテキストエディタと submit ボタンだけのシンプルな構成のもので、submit すれば、下部に文字列化した JSONデータが表示される。
入力したデータを視覚してほしかったから、<pre>{JSON.stringify(raw, null, 2)}</pre>
を含めているけれど、本来ならば submit
関数で処理が完了するから、そもそも const [raw, setRaw] = useState();
の定義がいらない。
useForm
が発行した control
を useController
に渡すことで onChange
と value
が用意される。これを <Editor>
の props に流し込めば、リッチテキストエディタも React Hook Form 経由で入力値を参照できるようになる。
もしリッチテキストエディタを複数配置することになったならば、それにともない配置数と同数の useController
の実行が求められる。そのようなときはリッチテキストエディタと useController
を切り出して、コンポーネントにしてしまえばいい。
まとめ
以上、React Hook Form と Draft.js の組み合わせ方に関する共有だった。
実装環境の項目に示したとおりに各種パッケージのバージョンを合わせてもらえば再現できると信じている。ただし React Hook Form のバージョンが 7 未満だった場合は、useController
ではなく、<Controller>
を用いなければならないことに注意してほしい。
リッチテキストエディタ自体を設置する要件というのは、それほど多いわけではない。けれども、いざ実装しようということになると、フォーム周りの装いに合わせたいと感じてしまうものだ。
このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。