【BlockNote入門】ReactでNotion風のメモアプリを作る方法

# はじめに
この記事では、Notion風のテキストエディタ環境を簡単に作れる**BlockNote**というReactライブラリを紹介していきます。

https://www.blocknotejs.org/

BlockNoteを使ってメモを書いている様子↓

![blocknote.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/11afaa3a-d641-bd93-5d73-b242204bfdad.gif)

# 使い方
## インストールと最初のセットアップ
まずはReactの環境を構築します。

```
npx create-react-app --template typescript myapp
```

以下のコマンドを打って開発用サーバを起動し、以下の画像のような画面が出れば成功です。

```
npm start
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/dec3a49c-a019-a305-553b-77e015b8fcf6.png)

ここまできたら一旦開発用サーバを停止し、BlockNoteをインストールします。

```
npm install @blocknote/core @blocknote/react @blocknote/mantine
```

インストールが終わったら`src/App.tsx`を以下のように書き換えます。

```src/App.tsx
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
 
export default function App() {
  const editor = useCreateBlockNote();

  return <BlockNoteView editor={editor} />;
}
```

再び開発用サーバを立ち上げ、以下のような画面が表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/736be68a-d93f-07c3-ccc2-cf341295c8a4.png)

## 日本語化

このままでは英語表示で使いづらいので日本語化します。

`src/App.tsx`を以下のように書き換えます。

```src/App.tsx
import { locales } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";

export default function App() {
    const editor = useCreateBlockNote({
        dictionary: locales.ja,  // 日本語化
    });

    return <BlockNoteView editor={editor} />;
}
```

無事に日本語になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/01adbd4f-aaad-4865-cf63-e3ee5fc7c059.png)

https://www.blocknotejs.org/examples/basic/localization

## 保存方法

https://www.blocknotejs.org/examples/backend/saving-loading

このままではリロードすると書いた内容が消えてしまうので、保存できるようにしていきます。

参考として、ローカルストレージに保存する方法を紹介します。
場合に応じてAPIやデータベースに保存するように変更してください。

```src/App.tsx
import { locales } from "@blocknote/core";
import { Block, BlockNoteEditor, PartialBlock } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useEffect, useMemo, useState } from "react";

async function saveToStorage(jsonBlocks: Block[]) {
    // ローカルストレージにコンテンツを保存する。
    // 場合に応じてAPIやデータベースに保存するように変更する。
    localStorage.setItem("editorContent", JSON.stringify(jsonBlocks));
}

async function loadFromStorage() {
    // 前のエディターの内容を取得する。
    const storageString = localStorage.getItem("editorContent");
    return storageString ? (JSON.parse(storageString) as PartialBlock[]) : undefined;
}

export default function App() {
    const [initialContent, setInitialContent] = useState<PartialBlock[] | undefined | "loading">("loading");

    // 前のエディターの内容をロードする。
    useEffect(() => {
        loadFromStorage().then((content) => {
            setInitialContent(content);
        });
    }, []);

    // 初期コンテンツがロードされるまでエディターの作成を遅らせるようにするため、
    // useCreateBlockNoteを使わずにuseMemo + createBlockNoteEditorを使う。
    const editor = useMemo(() => {
        if (initialContent === "loading") {
            return undefined;
        }
        return BlockNoteEditor.create({
            initialContent: initialContent,
            dictionary: locales.ja,
        });
    }, [initialContent]);

    if (editor === undefined) {
        return "Loading content...";
    }

    return (
        <BlockNoteView
            editor={editor}
            onChange={() => {
                saveToStorage(editor.document);
            }}
        />
    );
}
```

以下の動画のようにリロードしてもメモした内容が消去されなくなっていれば成功です。

![blocknoteSave.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/702be4fd-db5e-ed92-7326-639b145ca462.gif)

# さいごに

最後まで読んでいただき、ありがとうございました。

今回の記事では、ReactでNotion風のメモアプリを作る方法を紹介しました。
サンプルコードは以下のGithubに置いてあります。

https://github.com/MRyutaro/sample_blocknote

スタイルの変更方法やファイルのアップロード方法の紹介などもこれから追加していこうと思っています。

ハートを押していただけると記事投稿のモチベーションが上がるのでよろしくお願いします！
また、誤字・脱字や意見などがあればコメントしていただけると助かります。