tinymce / tinymce-react

Offical TinyMCE React component
MIT License
937 stars 152 forks source link

uncontrolled Editor component does not synchronise content #484

Closed jacob-orbiit closed 7 months ago

jacob-orbiit commented 7 months ago

What is the current behavior? Describe the bug

TinyMCE React's docs state that the "component is designed to be used as an uncontrolled component"; however, it does not correctly function when uncontrolled: it does not update the value of the form control (ex <textarea>) it creates, which causes its content to be stale.

And note that <Editor onEditorChange={(v, editor) => editor.save()}> does not trigger a change event. I'm guessing this is because you use DOM manipulation (which needs to be done in a very specific way to work in react).

Please provide the steps to reproduce and if possible a minimal demo of the problem via fiddle.tiny.cloud or similar.

There is no option to save an example using that fiddle. However, the issue is reproducible as-is:

  1. Load the fiddle
  2. Type "hello world" into the editor
  3. Open browser DevTools' Element inspector
  4. Select the textarea (search for mce_0)
  5. Open the console sub-panel, and enter $0.value
    • the output is '' (when the editor is initialised without any content) instead of 'hello world'

https://github.com/tinymce/tinymce/assets/101106010/3aba26db-3ccc-4301-8def-4a8ce92645d9

What is the expected behavior?

The textarea's value should be synchronised with the content of the editor.

Which versions of TinyMCE, and which browser / OS are affected by this issue? Did this work in previous versions of TinyMCE?

TinyMCE React: v4.3.2 Brave: v1.60.118 / Chromium: 119.0.6045.163 (arm64)

exalate-issue-sync[bot] commented 7 months ago

Internal Ref: INT-3257

danoaky-tiny commented 7 months ago

The reason for this behaviour is because the internal TinyMCE editor instance is setup within an iframe, and so all the text content changes happen within another body element in that iframe, not on the textarea you pointed to. You can see for yourself if you dig through the iframe in fiddle. You can however set the Editor to inline mode like in this example: https://tinymce.github.io/tinymce-react/?path=/story/editor--inline-editor. But that only then sets text content within a div, not a textarea, so no onchange events.

I hope that clears up why it's implemented this way, and why the "uncontrolled" route is generally preferred.

jacob-orbiit commented 7 months ago

Hiya! Thanks for the explanation. It does not however address the problems, nor does your tech design preclude addressing it (it only makes doing it properly slightly more complicated—but something you could easily encapsulate into a small internal utility).

Thanks, I saw the inline mode option, but as you yourself mentioned, it does not address the problem.

To repeat from my original post: onChange (the react callback) is not triggered when you do update the textarea because you assign to textarea.value via the DOM. You need to add an extra step to manually trigger the change event. A full explanation of the problem you've created as well as how to fix it are described in the link in my original post.

We unfortunately can't use your product with these defects.

If you do decide to keep the defect, you should at least update your docs that claim it can be used as an uncontrolled component, as that is just not true.