🐛 exposed Monaco Editor and `onChange` do not reflect actual state of Monaco contents
See original GitHub issueDescribe the bug
The underlying Monaco state in React is not accurately reflected in scenarios where users make a change, and then quickly un-make that change. This state does not ever resolve itself unless a user intercepts and makes an additional change.
It’s possible this is a bug in Monaco itself, but hopefully upgrading the version of Monaco could help resolve this.
To Reproduce
Steps to reproduce the behavior:
- Put a
console.log(contents)
in theonChange=
ofEditor
- Type a character (like “T”)
- Quickly hit backspace
- Notice that
onChange
only fires once.
You could also grab the editor
object from onMount
and run getValue()
at this time – note that the file contents will still have a “T” in them from your edited changes.
(If you keep alternating between “T” and “Backspace” you will notice that it will fire onChange
for every other change, the addition of the “T”, or if you type a T … wait a few seconds and then start alternating “Backspace” and then “T” you will only get the backspace onChange
events.)
Expected behavior
Any change should be captured accurately in onChange
. At a minimum, the exposed editor
object should be able to get the accurate file contents in these “change/unchange” scenarios
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:9 (3 by maintainers)
Top GitHub Comments
@suren-atoyan I’ll outline my understanding and hopefully this can help!
We are avoiding use of the
value=
param altogether in favor of interacting withmonaco
itself because of this issue –defaultValue=
works as expected!value=
has a lingering state problem that makes things difficult for us. We’re writing a Web IDE that has git interactions, i.e. at a minimum example, the ability to revert. I’ve approachedvalue=
with 3 strategies, none of which works:Only update
value=
explicitly when we want to override what the user has in there. This works fairly well but has a big problem. Let’s say that the last commit was just the string “A”. (value="A"
). The user replaces this with “B”. (value="A"
). When the user attempts to hit the revert button, we have no means of interfacing with the react component to tell it “update your value!” since the value we want to update it to is the already the value being passed in.Attempt to update
value=
all the time to avoid this earlier problem. Every keystroke, we call a debounce function which writes to our file cache, so ~50ms later we get the state the user had typed in. If we pass in this updated value intovalue=
while the user is typing, we will continually overwrite what the user is typing, or even if we shorten this feedback loop, we had a number of bugs reported around the cursor jumping around while the user is typing because of this configurationOnly set
value=
to a string for 1 render in order to force an overwrite and then switchvalue={undefined}
for all other times. This was difficult to manage state and ultimately anti-react-pattern-y so ultimately we’ve decided to fully abandon using thevalue
/defaultValue
interface in favor of just interfacing with themonaco
instance and its models directly.@heysweet this is really important, let me know once you have more information about this.