A React wrapper with no dependencies of its own
Monaco Editor for React.
At a glance
- What is it?
- react-monaco-editor is a thin component around Microsoft's editor, and its documentation is a list of caveats: a webpack example that stops mid attribute, a CSS Modules collision that needs two loader rules, an overrideServices prop documented as unstable, and a package manifest with three peers, no test script and a homepage pointing back at itself.
- Who is it for?
- This wrapper earns its place only if you are already committed to Monaco, because everything hard about it is the same hard thing: the editor has to be wired into your bundler, its stylesheets have to be kept out of your CSS Modules pipeline, and its language grammars have to be declared or highlighting simply will not appear.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 26 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The webpack example stops in the middle of an attribute
The main integration sample builds a class component with a `code` state field, an `editorDidMount` handler that logs and focuses the editor, an `onChange(newValue, e)` handler, and an options object carrying `selectOnLineNumbers: true`. It then opens a `MonacoEditor` element and stops there, on the line `width=`.
So the sample never finishes: there is no height, no language, no value prop and no closing bracket to copy. Everything the sample establishes is the shape of the callbacks and the fact that the editor is configured through an `options` object rather than through individual props.
That gap matters because the properties table further down is where the rest of the story is told, and it describes a component whose whole surface is optional. The sample is the only place showing how the pieces fit together, and it is the one section of the page that ends early.
Nothing is a runtime dependency, and React is capped below 20
The manifest has no dependencies block at all. What it has is three peer dependencies:
"peerDependencies": {
"monaco-editor": "^0.55.1",
"react": ">=16.8.0 <20.0.0",
"react-dom": ">=16.8.0 <20.0.0"
}So the editor itself is not bundled and never will be. You install Microsoft's package alongside this one, and the two are versioned together by hand at `^0.55.1` on both sides.
The React range is the more interesting one, because it is bounded at both ends while the development dependencies are not. `react` and `react-dom` sit at `^19.0.0` with `@types/react` at `^19.0.2`, which means the wrapper is built and tested on React 19 while refusing installation alongside React 20. TypeScript is `^5.1.6` and the compiler is the whole build step, since the build script is simply `tsc`.
Monaco's own CSS will collide with CSS Modules
The page names this as a side note, and it is the most likely thing to cost an afternoon. Monaco Editor imports its own CSS, so a project using CSS Modules gets a conflict by default, and the fix is to split the css-loader configuration into two rules keyed on path:
// Specify separate paths
const path = require('path');
const APP_DIR = path.resolve(__dirname, './src');
const MONACO_DIR = path.resolve(__dirname, './node_modules/monaco-editor');
{
test: /\.css$/,
include: APP_DIR,
use: [{
loader: 'style-loader',
}, {
loader: 'css-loader',
options: {
modules: true,
namedExport: true,
},
}],
}, {
test: /\.css$/,
include: MONACO_DIR,
use: ['style-loader', 'css-loader'],
}Your own source directory gets the Modules treatment with `namedExport: true`; the copy inside node_modules gets plain loaders. The second path is written out as a resolved directory rather than a package name, which means the split breaks the moment the layout of node_modules changes under a different package manager.
No highlighting means the plugin was never added
The first entry in the documentation's own question and answer section covers the failure everyone hits: no syntax highlighting, no autocomplete, no validation. The answer is not a prop. It is to add the Monaco Webpack plugin, or to follow Microsoft's instructions for loading the ESM build.
The plugin configuration in the sample asks for one language:
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
plugins: [
new MonacoWebpackPlugin({
// available options are documented at https://github.com/microsoft/monaco-editor/blob/main/webpack-plugin/README.md#options
languages: ['json']
})
]
};A `languages` list is required, and the list you pass is the list of grammars that end up in the bundle. The sample restricting itself to `json` is the whole lesson: anything you leave out is a language with no highlighting, and the failure looks identical to a broken editor.
overrideServices is documented as unstable in its own row
Every property is optional. `width` and `height` default to `100%`, `value`, `defaultValue` and `language` seed the model the component creates for you, and `theme` and `options` forward to the editor, with `options` pointed at Monaco's `IStandaloneEditorConstructionOptions` interface.
`overrideServices` is the one with a warning attached. It refers to Monaco's `IEditorOverrideServices` interface, and the documentation says in as many words that it depends on Monaco's internal implementations and may change over time, pointing at a specific comment on an issue in Microsoft's repository as the thing to read. That is an accurate description of what the prop is, and it is also a statement that this wrapper cannot promise the prop will keep working.
The four lifecycle callbacks sit next to it: `onChange(newValue, event)`, `editorWillMount(monaco)`, `editorDidMount(editor, monaco)` and `editorWillUnmount(editor, monaco)`, each described by analogy to the React lifecycle method with the same intent.
One theme at a time, and a diff editor with its own props
Multiple themes are answered with a flat refusal and a link: Monaco supports one theme. Any idea of switching themes per component is settled before it is asked.
The diff view is a separate export with a prop shape that does not match the single editor. `MonacoDiffEditor` takes `original` and `value` as its two sides, plus width, height, language and options, and the sample turns off side-by-side rendering by commenting the option out:
import { MonacoDiffEditor } from 'react-monaco-editor';
class App extends React.Component {
render() {
const code1 = "// your original code...";
const code2 = "// a different version...";
const options = {
//renderSideBySide: false
};
return (
<MonacoDiffEditor
width="800"
height="600"
language="javascript"
original={code1}
value={code2}
options={options}
/>
);
}
}The `original` and `value` naming is the thing to remember, since the single editor uses `value` for the same idea and a reader moving between the two will reach for `value` on both sides.
No test script, two lockfiles, and a homepage pointing at the repository
The scripts are `preversion`, `build`, `clean`, `format`, `lint` and `prepublishOnly`. There is no test script and no test runner in the development dependencies, in a package whose documentation spends most of its length answering questions about rendering. Publishing runs lint and build, which is the closest thing to a gate.
Two details of the manifest are worth a look. There is no `files` field and a `.npmignore` instead, so what ships is defined by an ignore list. And the entry fields disagree on a filename: `main` points at `lib/index.js` while `module` points at `lib/index` with no extension.
The example directory is a second project with its own `index.html`, `index.js`, `package.json`, `webpack.config.js` and `yarn.lock`, built by running yarn in the root and again inside it before starting on port 8886. That means the root lockfile and the example lockfile can disagree about the editor version. Two smaller slips come with them: the create-react-app instructions tell you to edit the `packages.json` scripts section, and one of the three authors has a misspelled address in the manifest.
Editorial conclusion
This wrapper earns its place only if you are already committed to Monaco, because everything hard about it is the same hard thing: the editor has to be wired into your bundler, its stylesheets have to be kept out of your CSS Modules pipeline, and its language grammars have to be declared or highlighting simply will not appear. Before adopting it, check the peer ranges against your own React and Monaco versions, since React is capped below 20.0.0 while development happens on 19, and read the overrideServices warning before you build anything on top of it. And if you are evaluating editors in general, this repository does not answer that question: it wraps one editor and links to the others.
Frequently asked questions
Is the Monaco editor free?
This repository is released under the MIT license and says nothing about the licence of the editor it wraps. Monaco Editor is a separate package from Microsoft that you install yourself, and its version is tied to this wrapper's peer range of ^0.55.1.
What is the best editor for React?
This repository does not compare editors. It wraps one of them, Microsoft Monaco, exposing a single editor component and a separate diff editor, and links to the upstream project for everything else.
Why is react-monaco-editor showing no syntax highlighting?
The documented answer is the Monaco Webpack plugin, whose languages option decides which grammars are bundled; the sample passes only json. The alternative is to load the ESM build of Monaco following Microsoft's own integration instructions.
How do I read the current value out of react-monaco-editor?
Two routes are given: use the first argument of editorDidMount, or hold a ref. With a ref the documented calls are this.refs.monaco.editor.getValue(), or reaching the model first with getModel() and then calling getValue() on it.
Which React versions does react-monaco-editor support?
The peer range for both react and react-dom is >=16.8.0 <20.0.0. Development happens against React 19, with react and react-dom at ^19.0.0 and @types/react at ^19.0.2 in the development dependencies.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/react-monaco-editor-react-monaco-editor)