Double render in React Strict Mode for MonacoEditorReactComp
Hi the below code, does not work with React StrictMode double render.
const CodeEditorComponent = forwardRef((props: IProps, ref: ForwardedRef<IEditorForwadedRef>) => {
let editorRef: any = useRef(null);
const onMonacoLoad = useCallback((wrapper: MonacoEditorLanguageClientWrapper) => {
editorRef = wrapper;
}, []);
return (
<MonacoEditorReactComp onLoad={onMonacoLoad} userConfig={getUserConfig(props)} style={{height: "inherit"}} />
);
});
Below is the error message: `
You cannot update the code resources as neither editor or diff editor is available.
at EditorAppExtended.updateCodeResources (http://localhost:3000/static/js/vendors-node_modules_typefox_monaco-editor-react_dist_index_js.chunk.js:58304:29)
at MonacoEditorLanguageClientWrapper.updateCodeResources (http://localhost:3000/static/js/vendors-node_modules_typefox_monaco-editor-react_dist_index_js.chunk.js:59261:28)
at MonacoEditorReactComp.componentDidUpdate (http://localhost:3000/static/js/vendors-node_modules_typefox_monaco-editor-react_dist_index_js.chunk.js:58044:20)
at commitLayoutEffectOnFiber (http://localhost:3000/static/js/bundle.js:67009:34)
at commitLayoutMountEffects_complete (http://localhost:3000/static/js/bundle.js:68150:13)
at commitLayoutEffects_begin (http://localhost:3000/static/js/bundle.js:68139:11)
at commitLayoutEffects_begin (http://localhost:3000/static/js/bundle.js:68122:15)
at commitLayoutEffects (http://localhost:3000/static/js/bundle.js:68085:7)
at commitRootImpl (http://localhost:3000/static/js/bundle.js:69994:9)
at commitRoot (http://localhost:3000/static/js/bundle.js:69874:9)
`
I'm using websocket to connect to gopls below is the JSONRPCRequest `
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":null,"clientInfo":{"name":"Code - OSS","version":"1.92.1"},"locale":"en","rootPath":"c:\\Users\\vivek\\streamcraft\\execution","rootUri":"file:///c%3A/Users/vivek/streamcraft/execution","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"foldingRange":{"refreshSupport":true},"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode","data"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":true},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true,"rangesSupport":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"trace":"off","workspaceFolders":[{"uri":"file:///c%3A/Users/vivek/streamcraft/execution","name":"execution"}]}}
Hi @vivekburman did you observe this with the current version? Can you reproduce this in a unit test or can you try to re-produce it in one the examples here: https://github.com/TypeFox/monaco-languageclient/blob/main/packages/examples/src/langium/statemachine/main-react.tsx Thank you
I can confirm that it double renders when running React: Langium Statemachine Language Client & Language Server (Worker) in strict mode on the latest version (c5f770b)
[vite] connecting... client:789:9
[vite] connected. client:912:15
Langium worker URL: /packages/examples/src/langium/statemachine/worker/statemachine-server.ts?worker_file&type=module main.ts:93:11
GET
http://localhost:20001/favicon.ico
[HTTP/1.1 404 Not Found 0ms]
Starting statemachine-server... statemachine-server-start.ts:8:11
DEBUG Initializing vscode services. Caller: monaco-editor (497124) chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: fileService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textFileService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: filesConfigurationService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: elevatedFileService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: configurationService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: contextService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textResourceConfigurationService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: workspaceEditingService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: workspacesService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textResourcePropertiesService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: configurationResolverService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: languageService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: ILanguageStatusService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: environmentService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: loggerService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: logService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: IDefaultLogLevelsService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textModelService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: keybindingService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: keyboardLayoutService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: commandService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: lifecycleService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: timerService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: localizationService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: languagePackService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textMateTokenizationFeature chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: themeService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: codeEditorService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: editorService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: textEditorService chunk-A3FVZIJ6.js:1382:21
DEBUG Loading service: editorGroupsService chunk-A3FVZIJ6.js:1382:21
DEBUG Initialization of vscode services completed successfully. chunk-A3FVZIJ6.js:1382:21
INFO Init of EditorApp was completed. chunk-A3FVZIJ6.js:1391:21
DEBUG Current model URIs: chunk-A3FVZIJ6.js:1382:21
DEBUG file:///workspace/example.statemachine chunk-A3FVZIJ6.js:1382:21
DEBUG All model references are disposed. chunk-A3FVZIJ6.js:1382:21
INFO Starting monaco-editor (497124) chunk-A3FVZIJ6.js:1391:21
text: statemachine TrafficLight
events
switchCapacity
next
initialState PowerOff
state PowerOff
switchCapacity => RedLight
end
state RedLight
switchCapacity => PowerOff
next => GreenLight
end
state YellowLight
switchCapacity => PowerOff
next => RedLight
end
state GreenLight
switchCapacity => PowerOff
next => YellowLight
end
textOriginal: main-react.tsx:54:19
Received message from main thread:
Object { jsonrpc: "2.0", id: 0, method: "initialize", params: {…} }
statemachine-server-start.ts:12:13
DEBUG Initialization of vscode services can only performed once! chunk-A3FVZIJ6.js:1382:21
INFO Init of EditorApp was completed. chunk-A3FVZIJ6.js:1391:21
Received message from worker:
Object { jsonrpc: "2.0", id: 0, result: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "initialized", params: {} }
statemachine-server-start.ts:12:13
INFO languageClientWrapper (unnamed): Started successfully. chunk-A3FVZIJ6.js:1391:21
Received message from main thread:
Object { jsonrpc: "2.0", method: "textDocument/didOpen", params: {…} }
statemachine-server-start.ts:12:13
INFO Starting monaco-editor (156350) chunk-A3FVZIJ6.js:1391:21
Element already has context attribute <anonymous code>:1:145535
text: statemachine TrafficLight
events
switchCapacity
next
initialState PowerOff
state PowerOff
switchCapacity => RedLight
end
state RedLight
switchCapacity => PowerOff
next => GreenLight
end
state YellowLight
switchCapacity => PowerOff
next => RedLight
end
state GreenLight
switchCapacity => PowerOff
next => YellowLight
end
textOriginal: main-react.tsx:54:19
Received message from main thread:
Object { jsonrpc: "2.0", id: 0, method: "initialize", params: {…} }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", id: 0, method: "client/registerCapability", params: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 0, result: null }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "workspace/didChangeConfiguration", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 0, error: {…} }
statemachine-server-start.ts:12:13
Error: Unhandled method client/registerCapability chunk-74XMBUSP.js:74:9
Received message from worker:
Object { jsonrpc: "2.0", id: 1, method: "workspace/configuration", params: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 1, result: (1) […] }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", id: 2, method: "client/registerCapability", params: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 1, error: {…} }
statemachine-server-start.ts:12:13
Error in ConfigurationProvider initialization: Error: Unhandled method workspace/configuration
_ResponseError messages.js:71
handleResponse connection.js:565
handleMessage connection.js:345
processMessageQueue connection.js:362
timer connection.js:334
chunk-3TUZ2NQ4.js:1716:107
Received message from main thread:
Object { jsonrpc: "2.0", id: 2, result: null }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", method: "textDocument/publishDiagnostics", params: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 2, error: {…} }
statemachine-server-start.ts:12:13
Error: Unhandled method client/registerCapability chunk-74XMBUSP.js:74:9
Received message from worker:
Object { jsonrpc: "2.0", id: 0, result: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "initialized", params: {} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "textDocument/didOpen", params: {…} }
statemachine-server-start.ts:12:13
INFO languageClientWrapper (unnamed): Started successfully. chunk-A3FVZIJ6.js:1391:21
Received message from worker:
Object { jsonrpc: "2.0", method: "window/logMessage", params: {…} }
main-react.tsx:30:13
Received message from worker:
Object { jsonrpc: "2.0", method: "window/logMessage", params: {…} }
main-react.tsx:30:13
Received message from worker:
Object { jsonrpc: "2.0", id: 3, method: "client/registerCapability", params: {…} }
main-react.tsx:30:13
INFO getWorker: moduleId: workerMain.js label: TextMateWorker chunk-A3FVZIJ6.js:1391:21
Received message from main thread:
Object { jsonrpc: "2.0", id: 3, result: null }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "workspace/didChangeConfiguration", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 3, result: null }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "workspace/didChangeConfiguration", params: {…} }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", id: 4, method: "workspace/configuration", params: {…} }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 4, result: (1) […] }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 4, result: (1) […] }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", method: "textDocument/publishDiagnostics", params: {…} }
main-react.tsx:30:13
Source map error: Error: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Stack in the worker:parseSourceMapInput@resource://devtools/client/shared/vendor/source-map/lib/util.js:163:15
_factory@resource://devtools/client/shared/vendor/source-map/lib/source-map-consumer.js:1066:22
SourceMapConsumer@resource://devtools/client/shared/vendor/source-map/lib/source-map-consumer.js:26:12
_fetch@resource://devtools/client/shared/source-map-loader/utils/fetchSourceMap.js:83:19
Resource URL: http://localhost:20001/packages/examples/%3Canonymous%20code%3E
Source Map URL: installHook.js.map
INFO getWorker: moduleId: workerMain.js label: TextEditorWorker chunk-A3FVZIJ6.js:1391:21
Received message from main thread:
Object { jsonrpc: "2.0", id: 1, method: "textDocument/foldingRange", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 1, method: "textDocument/foldingRange", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 2, method: "textDocument/foldingRange", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 2, method: "textDocument/foldingRange", params: {…} }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", id: 1, result: (4) […] }
main-react.tsx:30:13
Received message from worker:
Object { jsonrpc: "2.0", id: 2, result: (4) […] }
main-react.tsx:30:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 3, method: "textDocument/documentSymbol", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 3, method: "textDocument/documentSymbol", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 4, method: "textDocument/documentSymbol", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", id: 4, method: "textDocument/documentSymbol", params: {…} }
statemachine-server-start.ts:12:13
Received message from worker:
Object { jsonrpc: "2.0", id: 3, result: (1) […] }
main-react.tsx:30:13
Received message from worker:
Object { jsonrpc: "2.0", id: 4, result: (1) […] }
main-react.tsx:30:13
Updating styles main-react.tsx:60:21
Received message from main thread:
Object { jsonrpc: "2.0", method: "$/setTrace", params: {…} }
statemachine-server-start.ts:12:13
Received message from main thread:
Object { jsonrpc: "2.0", method: "$/setTrace", params: {…} }
statemachine-server-start.ts:12:13
Hi @metp can you reproduce tbis with the deployed version: https://typefox.github.io/monaco-languageclient/ghp_react_statemachine.html ?
Works correctly on the deployed version, no double rendering. However, the checkbox for turning strict mode on is disabled.
You have to check that before pressing start.
Sorry, my fault, no double rendering, even if turned on.
No worries, thanks for your feedback. I will revisit the whole react component behaviour (see #919) also with regard to strict mode. Actually strict mode renders components twice. The current behaviour/implementation of the languageclient if configured in the react component is problematic.
Fixed by new major releases: [email protected] is available: https://www.npmjs.com/package/monaco-languageclient/v/10.0.0 @typefox/[email protected] is available: https://www.npmjs.com/package/@typefox/monaco-editor-react/v/7.0.0