LoginSignup
11
6

More than 5 years have passed since last update.

【Draft.js】convertFromHTMLでInline Stylesが消えてしまう時の対処法

Posted at

はじめに

Draft.jsでリッチテキストエディタを実装した際に、convertFromHTMLを使うとInline Stylesが消えてしまうので、その対処法を書こうと思います。

解決したい問題

今回作りたいのは、以下のdemoような文字色変更を実現するリッチテキストエディタです。
https://codepen.io/Kiwka/pen/oBpVve

やりたいこと:

  • リッチテキストエディタで編集後、ContentStateを(draft-js-import-htmlのstateToHTMLを用いて)HTMLに変換してデータベースに保存し、サイト上でrender。
  • もう一度編集する際は、データベースからHTMLコードを取得し、ContentStateを復元。

上手く行かなかったこと

stateToHTMLを用いてHTMLに変換するのは上手くいったが、
そのHTMLを再びContentStateに復元する際に、Inline Stylesが消えてしまう。

以下のissueと似た状況です:
https://github.com/facebook/draft-js/issues/623
https://github.com/facebook/draft-js/issues/418

リッチテキストエディタでこのようにテキストを編集したとします。
スクリーンショット 2018-08-10 2.53.34.png

まずはstateToHTMLを用いてHTMLに変換します。
optionsについてはこちらに書かれています。

qiita1.js
output() {
    let options = {
      inlineStyles: {
        red: { style: { color: 'red' } },
        orange: { style: { color: 'orange' } },
        yellow: { style: { color: 'yellow' } },
        green: { style: { color: 'green' } },
        blue: { style: { color: 'blue' } },
        indigo: { style: { color: 'indigo' } },
        violet: { style: { color: 'violet' } },
      },
    };
    const html = stateToHTML(
      this.state.editorState.getCurrentContent(),
      options,
    );
    return html;
  }

return結果:
<p>Te<span style="color:red">xt</span></p>
上手くいってますね!

しかし、このHTMLをContentStateに復元するのがとても厄介でした。
Draft.js公式のconvertFromHTMLを用いても、draft-js-import-htmlを用いても
復元されたContentStateは(HTMLで表すと):
<p>Text</p>
で、style属性が消えてしまいます。
なので、
HTMLをデータベースに保存しても、それを再びContentStateに復元することができません...

対処法

convertToRaw / convertFromRaw / stateToHTMLを組み合わせたら上手く行きました。
下図のように、データベースにJSON形式のraw stateを保存することで、
HTMLにも変換できますし、contentStateもしっかり復元されます。
スクリーンショット 2018-08-14 22.34.32.png

まずはcontentStateをraw stateに変換して

const rawState = JSON.stringify(
      convertToRaw(this.state.editorState.getCurrentContent()),
    );

このrawStateをデータベースに保存します。(JSON.stringifyしないとエラーが出ます)

ContentStateに復元したい場合
データベースからrawStateを取得して、

qiita2.js
componentWillMount() {
    const contentState = convertFromRaw(JSON.parse(rawState));
    this.setState = {
      editorState: EditorState.createWithContent(contentState),
    };
  }

HTMLに変換したい場合
データベースからrawStateを取得して、

qiita3.js
output() {
    const contentState = convertFromRaw(JSON.parse(rawState));
    let options = ...//先ほどと同じなので省略
    const html = stateToHTML(
      contentState,
      options,
    );
    return html;
  }

これで上手くいくはずです!

終わりに

Draft.jsに関する日本語の記事が少なかったので、今回Qiita初投稿してみました。
Reactを勉強し始めてまだ4ヶ月なので、理解が不十分でもしかしたらめちゃくちゃ勘違いしてるかもです...
もし間違いがあったり、もっと良い方法があったらぜひTwitter(@nkmt_acm)などで教えてください!

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6