Error in Render: "Typeerror: Cannot Read Property 'create' of Undefined" Vue
@monaco-editor/react ·
Monaco Editor for React · use the monaco-editor in whatsoever React application without needing to use webpack
(or rollup
/parcel
/etc) configuration files / plugins
v4
is here - to see what'due south new in the new version and how to migrate from v3
, please read this md (also, if yous need the old version README
, information technology'due south hither)
Synopsis
Monaco
editor wrapper for like shooting fish in a barrel/1-line integration with any React
application without needing to use webpack
(or whatever other module bundler) configuration files / plugins. Information technology can be used with apps generated by create-react-app
, create-snowpack-app
, vite
, Side by side.js
or any other app generators - you don't need to eject or rewire them. You can utilize it fifty-fifty from CDN without bundlers
Motivation
The monaco-editor is a well-known web technology based lawmaking editor that powers VS Code. This library handles the setup process of the monaco-editor
and provides a clean API
to interact with monaco
from whatsoever React
environment
Demo
Check it out!
Documentation
- Installation
- Introduction
- Usage
- Simple usage
- Become value
-
editor instance
-
monaco instance
-
useMonaco
-
loader/config
- Multi-model editor
-
onValidate
- Notes
- For
electron
users - For
Next.js
users
- For
- Create your own editor!
- Development / Playground
- Props
-
Editor
-
Diff Editor
-
Installation
npm install @monaco-editor/react
or
yarn add @monaco-editor/react
or you tin employ CDN
. Here is an case
NOTE: For TypeScript
type definitions, this package uses the monaco-editor package equally a peer dependency. And so, if you demand types and don't already have the monaco-editor bundle installed, y'all volition demand to exercise and so
Introduction
Too types, the library exports Editor
and DiffEditor
components, as well equally the loader
utility and the useMonaco
claw:
import Editor , { DiffEditor , useMonaco , loader } from "@monaco-editor/react" ;
Usage
Unproblematic usage
Here is an example of a elementary integration of monaco
editor with a React
project.
You merely need to import and render the Editor
component:
); } const rootElement = document.getElementById("root"); ReactDOM.return(
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 annotate" / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
Extended example
console.log('onValidate:', marker.message)); } return (
import React from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; function App ( ) { role handleEditorChange ( value , event ) { // here is the electric current value } role handleEditorDidMount ( editor , monaco ) { panel . log ( "onMount: the editor case:" , editor ) ; console . log ( "onMount: the monaco example:" , monaco ) } function handleEditorWillMount ( monaco ) { console . log ( "beforeMount: the monaco case:" , monaco ) ; } function handleEditorValidation ( markers ) { // model markers // markers.forEach(mark => console.log('onValidate:', marking.bulletin)); } return ( < Editor tiptop = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" onChange = { handleEditorChange } onMount = { handleEditorDidMount } beforeMount = { handleEditorWillMount } onValidate = { handleEditorValidation } / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
Get value
There are two options to get the current value:
- become the current model value from the
editor
instance
import React , { useRef } from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; office App ( ) { const editorRef = useRef ( goose egg ) ; role handleEditorDidMount ( editor , monaco ) { editorRef . electric current = editor ; } function showValue ( ) { alert ( editorRef . electric current . getValue ( ) ) ; } return ( < > < push button onClick = { showValue } >Show value< / button > < Editor acme = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" onMount = { handleEditorDidMount } / > < / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
- get the current model value via
onChange
prop
); } const rootElement = document.getElementById("root"); ReactDOM.render(
import React from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; function App ( ) { part handleEditorChange ( value , event ) { panel . log ( "here is the current model value:" , value ) ; } return ( < Editor height = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" onChange = { handleEditorChange } / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
(get the `DiffEditor` values via `editor` instance)
import React , { useRef } from "react" ; import ReactDOM from "react-dom" ; import { DiffEditor } from "@monaco-editor/react" ; role App ( ) { const diffEditorRef = useRef ( null ) ; part handleEditorDidMount ( editor , monaco ) { diffEditorRef . current = editor ; } function showOriginalValue ( ) { alert ( diffEditorRef . electric current . getOriginalEditor ( ) . getValue ( ) ) ; } function showModifiedValue ( ) { warning ( diffEditorRef . current . getModifiedEditor ( ) . getValue ( ) ) ; } render ( < > < button onClick = { showOriginalValue } >prove original value< / button > < button onClick = { showModifiedValue } >evidence modified value< / button > < DiffEditor elevation = "90vh" defaultLanguage = "javascript" original = "// the original code" modified = "// the modified code" onMount = { handleEditorDidMount } / > < / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
editor instance
The editor
example is exposed from the onMount
prop as a first parameter, the 2nd is the monaco
case
); } const rootElement = document.getElementById("root"); ReactDOM.render(
import React , { useRef } from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; role App ( ) { const editorRef = useRef ( null ) ; role handleEditorDidMount ( editor , monaco ) { // hither is the editor case // y'all can store it in `useRef` for further usage editorRef . current = editor ; } return ( < Editor height = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" onMount = { handleEditorDidMount } / > ) ; } const rootElement = certificate . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
monaco example
At that place are three options to go the monaco
case:
- via
onMount/beforeMount
); } const rootElement = document.getElementById("root"); ReactDOM.render(
import React , { useRef } from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; function App ( ) { const monacoRef = useRef ( nothing ) ; office handleEditorWillMount ( monaco ) { // here is the monaco instance // exercise something before editor is mounted monaco . languages . typescript . javascriptDefaults . setEagerModelSync ( truthful ) ; } function handleEditorDidMount ( editor , monaco ) { // hither is another way to become monaco instance // you can also store it in `useRef` for further usage monacoRef . current = editor ; } return ( < Editor height = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" beforeMount = { handleEditorWillMount } onMount = { handleEditorDidMount } / > ) ; } const rootElement = certificate . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
- via
loader
utility
console.log("here is the monaco isntance:", monaco)); ">
import { loader } from "@monaco-editor/react" ; loader . init ( ) . then ( monaco => panel . log ( "here is the monaco isntance:" , monaco ) ) ;
codesandbox
- via
useMonaco
claw
{ if (monaco) { console.log("here is the monaco isntance:", monaco); } }, [monaco]); return (
import React from "react" ; import ReactDOM from "react-dom" ; import Editor , { useMonaco } from "@monaco-editor/react" ; function App ( ) { const monaco = useMonaco ( ) ; useEffect ( ( ) => { if ( monaco ) { console . log ( "here is the monaco isntance:" , monaco ) ; } } , [ monaco ] ) ; return ( < Editor top = "90vh" defaultValue = "// some comment" defaultLanguage = "javascript" / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . return ( < App / > , rootElement ) ;
codesandbox
useMonaco
useMonaco
is a React
hook that returns the instance of the monaco
. Only at that place is an important note that should exist considered: the initialization process is being handled by the loader
utility (the reference of @monaco-editor/loader): that process is beingness done asynchronously and but once. So, if the first initiator of the initialization is useMonaco
hook, the first returned value will exist null, due to its asynchronous installation. Just bank check the returned value of useMonaco
{ // do conditional chaining monaco?.languages.typescript.javascriptDefaults.setEagerModelSync(truthful); // or make sure that it exists by other ways if (monaco) { console.log("here is the monaco example:", monaco); } }, [monaco]); render (
import React , { useEffect } from "react" ; import ReactDOM from "react-dom" ; import Editor , { useMonaco } from "@monaco-editor/react" ; office App ( ) { const monaco = useMonaco ( ) ; useEffect ( ( ) => { // practise conditional chaining monaco ?. languages . typescript . javascriptDefaults . setEagerModelSync ( true ) ; // or make sure that information technology exists by other ways if ( monaco ) { panel . log ( "here is the monaco example:" , monaco ) ; } } , [ monaco ] ) ; return ( < Editor height = "90vh" defaultValue = "// some comment" defaultLanguage = "javascript" / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . return ( < App / > , rootElement ) ;
codesandbox
loader-config
The library exports (named) the utility chosen loader
. Basically, it's the reference of @monaco-editor/loader. By default, monaco
files are beingness downloaded from CDN
. There is an ability to change this beliefs, and other things concerning the AMD
loader of monaco
. We accept a default config file that you lot can modify past the style shown below:
import { loader } from "@monaco-editor/react" ; // you tin can change the source of the monaco files loader . config ( { paths: { vs: "..." } } ) ; // y'all tin configure the locales loader . config ( { "vs/nls": { availableLanguages: { "*": "de" } } } ) ; // or loader . config ( { paths: { vs: "..." , } , "vs/nls" : { availableLanguages: { "*": "de" , } , } , } ) ;
codesandbox
Notation: your passed object will exist deeply merged with the default ane
Multi-model editor
When y'all render the Editor
component, a default model is existence created. It's of import to mention that when you lot change the linguistic communication
or value
props, they affect the same model that has been car-created at the mountain of the component. In most cases information technology's okay, merely the developers face problems when they want to implement a multi-model editor to back up tabs/files similar in IDE
s. And previously to handle multiple models they had to do it manually and out of the component. Now, the multi-model API
is supported value
, language
and path
(monaco.editor.createModel(value, linguistic communication, monaco.Uri.parse(path))
). You can consider last one (path
) as an identifier for the model. The Editor
component, now, has a path
prop. When you lot specify a path
prop, the Editor
component checks if it has a model by that path or not. If yeah, the existing model will exist shown, otherwise, a new 1 will be created (and stored). Using this technique you tin can represent your files with paths, and create a fully multi-model editor. You can open your file, practice some changes, choose another file, and when you come up dorsum to the start ane the previous model will exist shown with the whole view state, text selection, undo stack, whorl position, etc. (simple demo)
Here is a unproblematic example: allow'south imagine we have a JSON
like representation of some file structure, something like this:
const files = { "script.js": { name: "script.js" , language: "javascript" , value: someJSCodeExample , } , "manner.css": { name: "style.css" , language: "css" , value: someCSSCodeExample , } , "index.html": { proper noun: "index.html" , linguistic communication: "html" , value: someHTMLCodeExample , } , }
And here is our simple multi-model editor implementation:
import React from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; office App ( ) { const [ fileName , setFileName ] = useState ( "script.js" ) ; const file = files [ fileName ] ; return ( < > < push disabled = { fileName === "script.js" } onClick = { ( ) => setFileName ( "script.js" ) } >script.js< / push > < push disabled = { fileName === "style.css" } onClick = { ( ) => setFileName ( "way.css" ) } >style.css< / push > < button disabled = { fileName === "index.html" } onClick = { ( ) => setFileName ( "index.html" ) } >index.html< / button > < Editor elevation = "80vh" theme = "vs-night" path = { file . name } defaultLanguage = { file . language } defaultValue = { file . value } / > < / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
The backdrop:
-
defaultValue
-
defaultLanguage
-
defaultPath
-
value
-
language
-
path
-
saveViewState
volition give you more flexibility in working with a multi-model editor.
Annotation
defaultValue
, defaultLanguage
, and defaultPath
are being considered only during a new model cosmos
value
, linguistic communication
, and path
are existence tracked the whole time
saveViewState
is an indicator whether to save the models' view states betwixt model changes or not
codesandbox
onValidate
onValidate
is an boosted property. An event is emitted when the content of the electric current model is changed and the electric current model markers are prepare. It will be fired with the current model markers
console.log("onValidate:", mark.message)); } return (
import React from "react" ; import ReactDOM from "react-dom" ; import Editor from "@monaco-editor/react" ; function App ( ) { function handleEditorValidation ( markers ) { // model markers markers . forEach ( marking => console . log ( "onValidate:" , mark . message ) ) ; } return ( < Editor height = "90vh" defaultLanguage = "javascript" defaultValue = "// let'due south write some broken code ๐" onValidate = { handleEditorValidation } / > ) ; } const rootElement = document . getElementById ( "root" ) ; ReactDOM . render ( < App / > , rootElement ) ;
codesandbox
Information technology's important to mention that according to monaco-editor, the whole supported languages are divided into two groups:
- languages that have rich
IntelliSense
and validation
-
TypeScript
-
JavaScript
-
CSS
-
LESS
-
SCSS
-
JSON
-
HTML
- languages with only basic syntax colorization
-
XML
-
PHP
-
C#
-
C++
-
Razor
-
Markdown
-
Unequal
-
Java
-
VB
-
CoffeeScript
-
Handlebars
-
Batch
-
Pug
-
F#
-
Lua
-
Powershell
-
Python
-
Ruby
-
SASS
-
R
-
Objective-C
As you can approximate, onValidate
prop will work only with the languages from the commencement grouping
Notes
For electron
users
As a usual React
component, this one also works fine with an electron-react environment, without need to accept a webpack
configuration or other extra things. But there are several cases that developers commonly face to and sometimes it can exist disruptive. Here they are:
- You lot see loading screen stuck Usually, information technology's because your environs doesn't permit you to load external sources. By default, it loads
monaco
sources fromCDN
. You can come across the default configuration. Merely sure you can modify that behavior; the library is fully configurable. Read about information technology here. And then, if you want to download it from your local files, yous can exercise it like this:
import { loader } from "@monaco-editor/react" ; loader . config ( { paths: { vs: "../path-to-monaco" } } ) ;
- Based on your electron surroundings it can exist required to have an absolute URL The utility function taken from here can help yous to achieve that. Let's imagine yous have
monaco-editor
package installed and you want to load monaco from thenode_modules
rather than from CDN: in that case, you tin can write something like this:
function ensureFirstBackSlash ( str ) { return str . length > 0 && str . charAt ( 0 ) !== "/" ? "/" + str : str ; } part uriFromPath ( _path ) { const pathName = path . resolve ( _path ) . supersede ( / \\ /grand , "/" ) ; return encodeURI ( "file://" + ensureFirstBackSlash ( pathName ) ) ; } loader . config ( { paths: { vs: uriFromPath ( path . join ( __dirname , "../node_modules/monaco-editor/min/vs" ) ) } } ) ;
There were several issues about this topic that can be helpful too - i two three 4
And if y'all utilize electron
with monaco
and react
and have faced an issue different than the above-discribed ones, please let us know to brand this section more helpful
For Next.js
users
Similar other React components, this ane also works with Next.js
without a hitch. The part of the source that should be pre-parsed is optimized for server-side rendering, and then, in usual cases, it will piece of work fine, but if you desire to have access, for instance, to monaco instance
yous should be aware that it wants to access the certificate
object, and it requires browser environment. Basically you simply need to avert running that role out of browser environment, at that place are several means to do that. The ane is described here
And if yous utilize monaco
with Next.js
and accept faced an issue different than the above-described one, please permit united states of america know to brand this section more helpful
Create your own editor
Under the hood this library uses @monaco-editor/loader that provides a utility called loader
. The loader
utility is a drove of functions that are being used to setup monaco
editor into your browser. loader.init()
handles the whole initialization process and returns the example of the monaco
- loader.init().so(monaco => console.log("hither is the monaco isntance:", monaco))
. The Editor
component uses this utility, gains access to monaco example
and creates the editor. Here is the implementation of the Editor
component. Yous can employ the same technique to create your own Editor
. You can but import the loader
utility, access to monaco instance
, and create your ain editor with your own custom logic. The shortest way to do information technology:
{ const wrapper = certificate.getElementById("root"); wrapper.style.meridian = "100vh"; const properties = { value: "part hello() {\due north\talert(\"Hello world!\");\n}", language: "javascript", } monaco.editor.create(wrapper, properties); }); ">
import loader from "@monaco-editor/loader" ; loader . init ( ) . then ( monaco => { const wrapper = document . getElementById ( "root" ) ; wrapper . fashion . height = "100vh" ; const properties = { value: "function hello() {\northward\talert(\"Hello globe!\");\n}" , language: "javascript" , } monaco . editor . create ( wrapper , properties ) ; } ) ;
That's all. You can wrap it into a React
component, or Vue
, or Angular
or leave information technology as vanilla i or whatsoever you want; it's written in pure js
codesandbox
Development-Playground
It's always important to have a place, where you lot tin play with the internals of the library. The playground
is a minimal React
app that directly uses the sources of the library. And then, if you lot are going to open a PR
, or desire to check something, or just want to try the freshest state of the library, you can run the playground and enjoy information technology
- clone the repository
git clone https://github.com/suren-atoyan/monaco-react.git
- go to the library folder
- install the library's dependencies
- get to the playground
- install the playground's dependencies
- and run the playground
monaco-react ├── playground │ ├── src/ # playground sources ├── src/ # library sources └── ...
If yous want to change something in the library, get to monaco-react/src/...
, the library will be automatically re-built and the playground will use the latest build
Props
Editor
Name | Type | Default | Description |
---|---|---|---|
defaultValue | string | Default value of the current model | |
defaultLanguage | string | Default language of the current model | |
defaultPath | string | Default path of the electric current model. Will exist passed as the third argument to .createModel method - monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath)) | |
value | string | Value of the current model | |
language | enum: ... | Linguistic communication of the electric current model (all languages that are supported by monaco-editor) | |
path | string | Path of the current model. Will be passed as the 3rd statement to .createModel method - monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath)) | |
theme | enum: "light" | "vs-dark" | "low-cal" | The theme for the monaco. Available options "vs-dark" | "lite". Define new themes past monaco.editor.defineTheme |
line | number | The line to jump on information technology | |
loading | React Node | "Loading..." | The loading screen before the editor volition exist mounted |
options | object | {} | IStandaloneEditorConstructionOptions |
overrideServices | object | {} | IEditorOverrideServices |
saveViewState | boolean | true | Indicator whether to save the models' view states betwixt model changes or not |
keepCurrentModel | boolean | false | Indicator whether to dispose the current model when the Editor is unmounted or non |
width | matrimony: number | string | "100%" | Width of the editor wrapper |
acme | matrimony: number | string | "100%" | Height of the editor wrapper |
className | string | Class name for the editor container | |
wrapperClassName | string | Form name for the editor container wrapper | |
beforeMount | func | noop | Signature: part(monaco: Monaco) => void An event is emitted before the editor is mounted. It gets the monaco case as a get-go argument |
onMount | func | noop | Signature: function(editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) => void An event is emitted when the editor is mounted. It gets the editor instance as a first argument and the monaco example as a 2nd |
onChange | func | Signature: function(value: string | undefined, ev: monaco.editor.IModelContentChangedEvent) => void An event is emitted when the content of the current model is changed | |
onValidate | func | noop | Signature: function(markers: monaco.editor.IMarker[]) => void An event is emitted when the content of the current model is changed and the current model markers are ready |
DiffEditor
Name | Type | Default | Description |
---|---|---|---|
original | string | The original source (left ane) value | |
modified | cord | The modified source (right one) value | |
linguistic communication | enum: ... | Language for the both models - original and modified (all languages that are supported by monaco-editor) | |
originalLanguage | enum: ... | This prop gives you the opportunity to specify the linguistic communication of the original source separately, otherwise, it will get the value of the language property | |
modifiedLanguage | enum: ... | This prop gives you the opportunity to specify the linguistic communication of the modified source separately, otherwise, it will become the value of language property | |
originalModelPath | string | Path for the "original" model. Will exist passed as a 3rd argument to .createModel method - monaco.editor.createModel(..., ..., monaco.Uri.parse(originalModelPath)) | |
modifiedModelPath | string | Path for the "modified" model. Will exist passed equally a third statement to .createModel method - monaco.editor.createModel(..., ..., monaco.Uri.parse(modifiedModelPath)) | |
keepCurrentOriginalModel | boolean | simulated | Indicator whether to dispose the electric current original model when the DiffEditor is unmounted or not |
keepCurrentModifiedModel | boolean | fake | Indicator whether to dispose the current modified model when the DiffEditor is unmounted or not |
theme | enum: "lite" | "vs-nighttime" | "calorie-free" | The theme for the monaco. Available options "vs-dark" | "light". Define new themes by monaco.editor.defineTheme |
line | number | The line to jump on it | |
loading | React Node | "Loading..." | The loading screen before the editor will be mounted |
options | object | {} | IDiffEditorConstructionOptions |
width | union: number | string | "100%" | Width of the editor wrapper |
height | union: number | string | "100%" | Height of the editor wrapper |
className | cord | Class name for the editor container | |
wrapperClassName | string | Class name for the editor container wrapper | |
beforeMount | func | noop | Signature: role(monaco: Monaco) => void An event is emitted before the editor mounted. It gets the monaco instance as a first statement |
onMount | func | noop | Signature: function(editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) => void An event is emitted when the editor is mounted. It gets the editor instance every bit a commencement argument and the monaco example as a second |
License
MIT
GitHub
https://github.com/suren-atoyan/monaco-reactSource: https://bestofreactjs.com/repo/suren-atoyan-monaco-react-react-rich-text-editing
0 Response to "Error in Render: "Typeerror: Cannot Read Property 'create' of Undefined" Vue"
Post a Comment