Arnav
Arnav

Reputation: 117

Unable to change theme in @monaco-editor/react

I was trying to change the theme of the @monaco-editor/react but I'm unable to do so. While developing the theme is changing but after refreshing the page it is unable to change the theme and turning into the default one.

import React, { useEffect, useRef, useState } from "react";
import axios from "axios";
// import MonacoEditor from "react-monaco-editor";
import Editor, { useMonaco } from "@monaco-editor/react";

//^ @themes
import { nightOwl } from "./style";

import "./Code.css";
import { c } from "./defaultCode";

const Code = () => {
  const monaco = useMonaco();
  const monacoRef = useRef(null);
  const [code, setCode] = useState(c);
  const [output, setOutput] = useState("Output");
  const [input, setInput] = useState("");
  const [isEditorReady, setIsEditorReady] = useState(false);

  const [outputLoading, setOutputLoading] = useState(false);

  const state = {
    code: c.c,
    result: "Submit Code to See Result",
    lang: "c",
  };

  const submitHandler = async (e) => {
    setOutputLoading(true);
    try {
      const { data } = await axios({
        method: "post",
        url: "http://localhost:5000/code",
        data: {
          code: code,
          input: input,
          lang: "c",
        },
      });
      // console.log(data, "<=data");

      if (data.error) {
        setOutput(data.error);
      } else {
        setOutput(data.output);
      }

      setOutputLoading(false);
    } catch (err) {
      console.log(err);
      setOutputLoading(false);
    }
  };

  const updateCode = (newCode, e) => {
    setCode(newCode);
  };

  const inputHandler = (e) => {
    setInput(e.target.value);
  };

  function handleEditorDidMount(editor, monaco) {
    monaco.editor.defineTheme("my-theme", nightOwl);
    monacoRef.current = editor;
    setIsEditorReady(true);
  }

  useEffect(() => {
    if (monaco) {
      console.log(monaco);
      monaco.editor.defineTheme("my-theme", nightOwl);
    }
  }, [monaco]);

  return (
    <>
      {/* <div className="filter" /> */}
      <header>
        <div className="header_container">
          <h1>Code</h1>
          <button onClick={submitHandler} id="run">
            Run
          </button>
        </div>
      </header>
      <div className="__code">
        <div className="left">
          <Editor
            id="code"
            width="80vw"
            height="90vh"
            // theme="vs-dark"
            theme="my-theme"
            smooth="2"
            options={{
              minimap: {
                enabled: false,
              },
              fontSize: 14,
              cursorStyle: "block",
              wordWrap: "on",
            }}
            value={code}
            onChange={updateCode}
            language={state.lang}
            editorDidMount={handleEditorDidMount}
          />
        </div>
        <div className="right">
          {outputLoading ? (
            <textarea
              name="outputLoad"
              id="output"
              cols="30"
              rows="7"
              data-gramm_editor="false"
              spellCheck="false"
              readOnly={true}
              value="Loading ..."
            ></textarea>
          ) : (
            <textarea
              name="output"
              id="output"
              cols="30"
              rows="7"
              data-gramm_editor="false"
              spellCheck="false"
              readOnly={true}
              value={output}
            ></textarea>
          )}
          <textarea
            name="input"
            id="input"
            cols="30"
            rows="7"
            data-gramm_editor="false"
            spellCheck="false"
            value={input}
            onChange={inputHandler}
            placeholder="Input"
          ></textarea>
        </div>
      </div>
    </>
  );
};

export default Code;

I tried to solve this using useMonaco hook under useEffect but it is still not working. Please help me to solve this issue.

Upvotes: 4

Views: 4778

Answers (2)

Rakshit Arora
Rakshit Arora

Reputation: 664

You can do something like this

<Editor
  beforeMount={setEditorTheme}
/>
function setEditorTheme(monaco: any) {
  monaco.editor.defineTheme('onedark', {
    base: 'vs-dark',
    inherit: true,
    rules: [
      {
        token: 'comment',
        foreground: '#5d7988',
        fontStyle: 'italic'
      },
      { token: 'constant', foreground: '#e06c75' }
    ],
    colors: {
      'editor.background': '#21252b'
    }
  });
}

You can search for relevant tokens by looking at open source themes like One Dark, Dracula etc For example this https://github.com/Binaryify/OneDark-Pro/blob/master/themes/OneDark-Pro-darker.json

Upvotes: 4

Mike Lischke
Mike Lischke

Reputation: 53337

The answer is in editor.api.d.ts:

    /**
     * Define a new theme or update an existing theme.
     */
    export function defineTheme(themeName: string, themeData: IStandaloneThemeData): void;

    /**
     * Switches to a theme.
     */
    export function setTheme(themeName: string): void;

You must call setTheme to activate your theme.

Both defineTheme and setTheme are global Monaco functions, not specific to a particular editor instance. Hence it makes no sense to call them on every mount action. Instead call them on app start and when you change the theme, only.

Upvotes: 3

Related Questions