Open2

Monaco エディターについて

Godai HoriGodai Hori

Sandpackにmonaco エディターを組み込む

https://codesandbox.io/s/vud7z?file=/src/App.tsx

最終的なコード

import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
import { useActiveCode, useSandpack, FileTabs } from "@codesandbox/sandpack-react";
import loader from "@monaco-editor/loader";
import { emmetHTML } from 'emmet-monaco-es'
import type { editor } from 'monaco-editor';

export function Editor() {
  const editorRef = useRef<HTMLDivElement>(null);
  const monacoEditorRef = useRef<editor.IStandaloneCodeEditor>(null);
  const { sandpack } = useSandpack();
  const { code, updateCode } = useActiveCode();
  
  useLayoutEffect(() => {
    (async () => {
      const monaco = await loader.init()
      const disposeHTML = emmetHTML(
        monaco,
        ['html'],
      )
      disposeHTML()
      const path = sandpack.activeFile;
      const activeFile = sandpack.files[path]
      const lang = sandpack.activeFile.split('.')[1]
      const editor = monaco.editor.create(editorRef.current, {
        value: activeFile.code,
        language: lang
      });
      editor.onDidChangeModelContent(() => {
        updateCode(editor.getValue());
      });
      monacoEditorRef.current = editor
    })()
    return () => {
      if (monacoEditorRef.current) {
        monacoEditorRef.current.dispose()
      }
    }
  }, []);

  useEffect(() => {
    if (monacoEditorRef.current && code !== monacoEditorRef.current.getValue()) {
      monacoEditorRef.current.getModel().setValue(code)
    }
  }, [code])

  return (<div>
    <FileTabs />
    <div ref={editorRef} style={{ height: "100vh" }} />
  </div>);
}