ReactでCodemirror6を使ってみた

## 概要
2022年の6月に新しく登場した「codemirror6」。以前は古いバージョンをVueで使っていましたが、今回初めてReactで使用してみました。  
一部、ドキュメントの通りにやってもうまく動かなかったので、備忘録として書いておきたいと思います。

## 注意点
今回は、C言語のエディタを作ることを想定していますが、他の言語や、Markdownのエディタも作れるようです。機会があれば記事にしたいと思います。

## 全体の流れ
1. Reactのプロジェクト作成（今回はViteを使います）
1. ライブラリのインストール
1. コンポーネントの読み込み・配置
1. 動作確認
1. 機能追加

## 詳細手順
### 1. Reactのプロジェクト作成
適当な作業フォルダを作って、VSCodeなどのエディタで開きます。
開いたら、そのディレクトリをカレントディレクトリとして、ターミナルで以下のコマンドを実行します。  
```
npm create vite@latest
```
表示される質問に答えてプロジェクトを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/3c06c23e-c198-6080-eb54-b5b45034064e.png)

作成できたら以下のようにreactに必要なコンポーネントをインストールします。
```
cd codemirror-sample
npm i
```
インストールが終わると、ディレクトリ構成が以下のようになっていると思います。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/6014d632-4f82-b153-26ad-c6ea9c5419f3.png">


サンプルを作るには余計なファイルが多すぎるので、
以下の作業を行って、シンプルな`App.tsx`だけにします。

＜作業＞
* App.cssとindex.cssの削除
* main.tsxから、`import './index.css'`の記述を削除
* App.tsxから、`import './App.css'`の記述を削除

加えて、App.tsxは以下の通りにします。
```App.tsx
function App() {
  return (
    <>
      <h1>Codemirror 6 サンプル</h1>
    </>
  );
}

export default App;
```

### 3. ライブラリのインストール
以下のコマンドをターミナルで実行して、React用のCodemirror（`react-codemirror`
）のライブラリをインストールします。
```
npm install @uiw/react-codemirror --save
```

### 4. コンポーネントの読み込み・配置
App.tsxを以下のように変更し、Codemirrorのコンポーネントを配置します。
```diff_javascript
+ import ReactCodeMirror from "@uiw/react-codemirror";
+ import { SetStateAction, useCallback, useState } from "react";

function App() {
+ const [value, setValue] = useState<string>("");

+ //コードが変更された時に呼ばれる更新関数（メモ化済み）
+ const onChange = useCallback((val: SetStateAction<string>) => {
+   setValue(val);
+ }, []);
  return (
    <>
      <h1>Codemirror 6 サンプル</h1>
+     <ReactCodeMirror value={value} onChange={onChange} />
    </>
  );
}

export default App;
```

### 5. 動作確認
以下のコマンドをターミナルで実行して、開発サーバを立ち上げます。
```
npm run dev
```
ブラウザで、`localhost:5173`にアクセスすると、以下のようなエディタが現れます。文字を入力してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/118c2190-3a03-55f9-0da2-544e063f330d.png)

これで導入ができました🎉

### 6. 機能追加
シンプルなエディタであればこれでもいいのですが、プログラミングのエディタのような使い方にするには、追加のライブラリをインストールする必要があります。  

#### プログラミング言語への対応
今回は、C言語（C++言語）のエディタを作ることを想定して、機能追加をしてみましょう。
他の言語や、Markdownのエディタも作れますので、ライブラリの一覧などはドキュメント（ https://github.com/uiwjs/react-codemirror?tab=readme-ov-file ）を参照してください。

それでは、C言語（C++言語）のエディタに必要なライブラリをインストールします。  
以下のコマンドをターミナルで実行してください。

```
npm i @codemirror/lang-cpp
```
次に、App.tsxに、機能追加のための記述をしていきます。  
具体的には、`<ReactCodeMirror>`の属性に、`extensions`を追加します。

```diff_javascript
+ import { cppLanguage } from "@codemirror/lang-cpp";
import ReactCodeMirror from "@uiw/react-codemirror";
import { SetStateAction, useCallback, useState } from "react";

function App() {
  const [value, setValue] = useState<string>("");

  //コードが変更された時に呼ばれる更新関数（メモ化済み）
  const onChange = useCallback((val: SetStateAction<string>) => {
    setValue(val);
  }, []);
  return (
    <>
      <h1>Codemirror 6 サンプル</h1>
      <ReactCodeMirror
        value={value}
        onChange={onChange}
+       extensions={[cppLanguage]}
      />
    </>
  );
}

export default App;

```

再度、開発サーバを起動して、動作確認してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/75c7e279-faf0-cce3-fcdf-0508fdb18e57.png)
`lang-cpp`というライブラリを追加したことで、コードのハイライトや、自動インデントに対応しました！

このようにCodemirrorでは、`extensions`に追加することで、機能を高めていくことができます。  

#### デザイン変更
さらに、**エディタのデザイン（Theme）を変更することもできます！**  
ドキュメントによれば、以下のようにたくさん種類があるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/1c8ca821-abe4-0414-c59d-ed5ffd213a4c.png)

試しに、`@uiw/codemirror-theme-xcode`というThemeをインストールしてみましょう。
```
npm i @uiw/codemirror-theme-xcode
```

以下のように、App.tsxを変更します。
```diff_javascript
import { cppLanguage } from "@codemirror/lang-cpp";
+ import { xcodeDark } from "@uiw/codemirror-theme-xcode";
import ReactCodeMirror from "@uiw/react-codemirror";
import { SetStateAction, useCallback, useState } from "react";

function App() {
  const [value, setValue] = useState<string>("");

  //コードが変更された時に呼ばれる更新関数（メモ化済み）
  const onChange = useCallback((val: SetStateAction<string>) => {
    setValue(val);
  }, []);
  return (
    <>
      <h1>Codemirror 6 サンプル</h1>
      <ReactCodeMirror
        value={value}
        onChange={onChange}
+       theme={xcodeDark}
        extensions={[cppLanguage]}
      />
    </>
  );
}

export default App;

```

動作確認してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/4cc5a4bf-86f2-23ec-c2f9-209e2398f1a0.png)

デザインが変わりました🎉  
個人的には、XcodeのThemeが好きです😊

## おわりに
以上、  
ReactでCodemirror6を使う方法をご紹介しました！  
途中紹介したように、Markdownのエディタとしても作ることができるようなので、時間が取れたらこれについてもやってみて、記事にしようかと思います！

## 参考文献
https://github.com/uiwjs/react-codemirror?tab=readme-ov-file