React Draft Wysiwygを使ってシンプルなテキストエディタを作成する

概要

今作っているアプリの中にテキストエディタを投入したいとなったので、取り急ぎ作成しました。

完成形

f:id:rinda_1994:20220116152606p:plain

環境

  • react 17.0.1
  • typescript 4.5.4
  • gatsby 4.3.0
  • @emotion/react 11.7.0
  • react-draft-wysiwyg 1.14.7

選定したライブラリ

react-draft-wysiwygを選びました。

これはDraft.jsという、Facebook社が開発しているテキストエディタ用ライブラリをさらに拡張させたライブラリです。

今回は「シンプル」かつ「欲しい機能が既に載っている」という点でこちらのライブラリを選びました。

素のDraft.jsや、その機能を拡張したDraft.js Plugins、その他Draft.jsを土台としたサードパーティなど、エディタを作っていく上で選択肢はいくつかあり、実際はじめはこれら別の選択肢に手を出したりしたのですが、結局以下の理由で採用しませんでした。

  • 欲しい機能を実装するにあたり、Draft.jsの情報源が少ないため、ニッチなところでつまづいた際の対応がむずかしい&時間がかかる
  • デフォルトのUIがごちゃごちゃしている
  • TypeScriptに対応していない
  • 長い間メンテナンスされていない

1個目の理由に関しては、例えば、範囲選択したときだけ表示されるツールバーを実装しようとした際、かな→漢字変換したときの範囲選択をケースから除外しようとして結局無理だったりしました🥲

したこと

1. react-draft-wysiwygのインストール

yarn add react-draft-wysiwyg

2. importと利用

こちらがエディタ用コンポーネントのコード全文です。説明の必要そうな箇所の意味を簡単に追っていきます!

import React from "react"
import { Link } from "gatsby"
import { Editor } from "react-draft-wysiwyg"
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css"
import { css } from "@emotion/react"

const Article = () => {
  return (
    <div
      onClick={focus}
      css={css`
        box-sizing: border-box;
        border: 1px solid #ddd;
        cursor: text;
        padding: 16px;
        border-radius: 2px;
        margin-bottom: 2em;
        box-shadow: inset 0px 1px 8px -3px #ababab;
        background: #fefefe;
      `}
    >
      <Editor
        toolbar={{
          options: ["inline", "blockType", "list", "textAlign", "link"],
          inline: {
            options: ["bold", "strikethrough"],
          },
          blockType: {
            inDropdown: false,
            options: ["H2"],
          },
          list: {
            options: ["unordered"],
          },
          textAlign: {
            options: ["center"],
          },
          link: {
            options: ["link"],
          },
        }}
      />
    </div>
  )
}

export default Article
import React from "react"
import { Editor } from "react-draft-wysiwyg"
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css"
import { css } from "@emotion/react"

適宜import。 import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css"はエディタのデフォルトのstyleを保つために必要。

    <div
      onClick={focus}
      css={css`
        box-sizing: border-box;
        border: 1px solid #ddd;
        cursor: text;
        padding: 16px;
        border-radius: 2px;
        margin-bottom: 2em;
        box-shadow: inset 0px 1px 8px -3px #ababab;
        background: #fefefe;
      `}
    >
   </div>

エディタへのCSS適用。枠線を濃くしたり、枠内に影つけたり。

      <Editor
        toolbar={{
          options: ["inline", "blockType", "list", "textAlign", "link"],
          inline: {
            options: ["bold", "strikethrough"],
          },
          blockType: {
            inDropdown: false,
            options: ["H2"],
          },
          list: {
            options: ["unordered"],
          },
          textAlign: {
            options: ["center"],
          },
          link: {
            options: ["link"],
          },
        }}
      />

エディタの表示。デフォルトのままだとツールバーのツールがてんこもり(20個くらいある?)なので、optionsなどのpropsでその辺を絞っています。

上記のコードだと太字(bold)、取り消し線(strikethrough)、見出し(H2)、箇条書き(unordered)、中央寄せ(center)、リンク(link)の機能を残しています。

3. 完成!

完成形の画像は記事の一番上にあります🙌

所感

実装超かんたん!

だけどDraft.jsというライブラリのさらにそのまたライブラリを使っているので、今後のメンテナンスが活発でない場合はReactや関連モジュールのアップデートのタイミングで妙なエラーとか出そうで怖い・・・