@monaco-editor/react Documentation

repository·master·Indexed 26 days ago

https://github.com/suren-atoyan/monaco-react

A React wrapper for the Monaco Editor (the engine powering VS Code) that allows embedding the editor into React applications without complex bundler configuration for Webpack, Vite, or Next.js. It provides Editor and DiffEditor components, the useMonaco hook, and a loader utility for configuring how Monaco is loaded, including support for CDN or local bundling.

Tokens
14.3K
Snippets
18
Records
35
Agent score
87%

What's inside @monaco-editor/react

  1. Overview of @monaco-editor/react

    master

    @monaco-editor/react is a wrapper for the Monaco Editor (the engine powering VS Code) designed for easy integration into any React application.

    Key features:

    • No bundler configuration required: Works with create-react-app, vite, Next.js, snowpack, etc., without needing to modify webpack or rollup configs.
    • React 19 support available via the @next tag.
    • Built with TypeScript.
    • Supports multi-model editing.
    • Integrated with @monaco-editor/loader.
  2. Configure type-aware ESLint rules for production

    master

    To enable type-aware linting in a production application, update your ESLint configuration to include parserOptions pointing to your tsconfig files and switch to type-checked rule sets.

    export default tseslint.config({
      languageOptions: {
        // other options...
        parserOptions: {
          project: ['./tsconfig.node.json', './tsconfig.app.json'],
          tsconfigRootDir: import.meta.dirname,
        },
      },
    })
  3. Use monaco-editor as an npm package (Vite setup)

    master

    Starting from v4.4.0, you can bundle monaco-editor locally instead of using a CDN. In a Vite environment, you must manually configure the MonacoEnvironment to handle web workers for different languages.

    import { loader } from '@monaco-editor/react';
    import * as monaco from 'monaco-editor';
    import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
    import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
    import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
    import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
    import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
    
    self.MonacoEnvironment = {
      getWorker(_, label) {
        if (label === 'json') {
          return new jsonWorker();
        }
        if (label === 'css' || label === 'scss' || label === 'less') {
          return new cssWorker();
        }
        if (label === 'html' || label === 'handlebars' || label === 'razor') {
          return new htmlWorker();
        }
        if (label === 'typescript' || label === 'javascript') {
          return new tsWorker();
        }
        return new editorWorker();
      },
    };
    
    loader.config({ monaco });
    loader.init().then(/* ... */);
  4. Implement a multi-model editor using the `path` prop

    master

    To support multiple files or tabs (like an IDE), use the path prop on the Editor component. When a path is provided, the component checks if a model with that path already exists. If it does, it reuses the existing model (preserving undo stack, scroll position, and text selection); otherwise, it creates a new one.

    Key Prop Behaviors:

    • defaultValue, defaultLanguage, and defaultPath: Used only during the initial creation of a new model.
    • value, language, and path: Tracked and applied continuously.
    • saveViewState: A boolean indicating whether to save the model's view state (scroll position, etc.) between model changes.
    import React, { useState } from 'react';
    import Editor from '@monaco-editor/react';
    
    const files = {
      'script.js': { name: 'script.js', language: 'javascript', value: 'console.log("hello");' },
      'style.css': { name: 'style.css', language: 'css', value: 'body { color: red; }' },
    };
    
    function App() {
      const [fileName, setFileName] = useState('script.js');
      const file = files[fileName];
    
      return (
        <>
          <button onClick={() => setFileName('script.js')}>script.js</button>
          <button onClick={() => setFileName('style.css')}>style.css</button>
          <Editor
            height="80vh"
            theme="vs-dark"
            path={file.name}
            defaultLanguage={file.language}
            defaultValue={file.value}
          />
        </>
      );
    }
  5. Configure Monaco loader for Electron (Offline Mode)

    master

    By default, @monaco-editor/react loads Monaco sources from a CDN. In Electron environments, you may need to load them locally to avoid loading screen hangs or to work offline.

    To load Monaco from your local node_modules, use loader.config with an absolute file URL.

    import { loader } from '@monaco-editor/react';
    import path from 'path';
    
    function ensureFirstBackSlash(str) {
      return str.length > 0 && str.charAt(0) !== '/' ? '/' + str : str;
    }
    
    function uriFromPath(_path) {
      const pathName = path.resolve(_path).replace(/\/g, '/');
      return encodeURI('file://' + ensureFirstBackSlash(pathName));
    }
    
    loader.config({
      paths: {
        vs: uriFromPath(path.join(__dirname, '../node_modules/monaco-editor/min/vs')),
      },
    });
  6. Use Monaco in Next.js

    master

    The Editor component works with Next.js, but because it requires a browser environment (to access the document object), you must ensure it is not executed during server-side rendering.

    Use dynamic imports with ssr: false to load the component only on the client side.

  7. Install @monaco-editor/react

    master

    You can install the package using npm, yarn, or via CDN.

    Note for React 19 users: Use @monaco-editor/react@next to ensure compatibility with React v19.

    Note for TypeScript users: This package uses monaco-editor as a peer dependency for type definitions. If you need TypeScript support and do not already have monaco-editor installed, you must install it manually.

    npm install @monaco-editor/react # or @monaco-editor/react@next for React v19
    
    # or
    
    yarn add @monaco-editor/react
  8. Get the current editor value

    master

    You can retrieve the current value of the editor in two ways:

    1. Via onChange prop: The most direct way to track changes.
    2. Via the editor instance: Store the editor instance in a useRef during the onMount event, then call editorRef.current.getValue().
  9. Configure eslint-plugin-react for React projects

    master

    To use eslint-plugin-react, install the plugin and update your eslint.config.js to include the React settings, plugins, and recommended rules (including jsx-runtime).

    // eslint.config.js
    import react from 'eslint-plugin-react'
    
    export default tseslint.config({
      // Set the react version
      settings: { react: { version: '18.3' } },
      plugins: {
        // Add the react plugin
        react,
      },
      rules: {
        // other rules...
        // Enable its recommended rules
        ...react.configs.recommended.rules,
        ...react.configs['jsx-runtime'].rules,
      },
    })
  10. Run the development playground

    master

    To test the latest library changes or contribute, you can run the playground app which uses the local library sources.

    1. Clone the repository: git clone https://github.com/suren-atoyan/monaco-react.git
    2. Navigate to the library folder: cd monaco-react
    3. Install dependencies: npm install
    4. Navigate to playground: cd playground
    5. Install playground dependencies: npm install
    6. Run the playground: npm run dev
    git clone https://github.com/suren-atoyan/monaco-react.git
    cd monaco-react
    npm install
    cd playground
    npm install
    npm run dev
  11. Configure the monaco loader

    master

    The loader utility allows you to customize how Monaco files are loaded. By default, they are fetched from a CDN. You can change the source paths or configure locales using loader.config().

    import { loader } from '@monaco-editor/react';
    
    // Change source of monaco files
    loader.config({ paths: { vs: '...' } });
    
    // Configure locales
    loader.config({ 'vs/nls': { availableLanguages: { '*': 'de' } } });
  12. Basic usage of the Editor component

    master

    To integrate the Monaco editor into a React project, import the Editor component and render it with required props like height, defaultLanguage, and defaultValue.

    import React from 'react';
    import ReactDOM from 'react-dom';
    import Editor from '@monaco-editor/react';
    
    function App() {
      return <Editor height="90vh" defaultLanguage="javascript" defaultValue="// some comment" />;
    }
    
    const rootElement = document.getElementById('root');
    ReactDOM.render(<App />, rootElement);