I'm trying to create a simple React markdown editor.
The component is completely controlled. The problem is: If the user selects abc
in the textarea and clicks the B button, I need to call onchange()
with **abc**
. I need to surround the text with these asterisks.
This difference between what I pass on the onchange()
and what the user has actually typed causes the textarea history to become inconsistent. Ctrl + Z doesn't work anymore.
Demo. [EDIT: This demo has the fix implemented. It's not as it was when I asked the question]
How can I trigger onchange()
on React with an arbitrary text and keep the Ctrl + Z consistent?
I didn't solve the problem but it's possibly the best I can do to without re-implementing history as @Rishat mentioned (If I'm mistaken, please let me know).
Thanks to this answer, I got to understand this command:
document.execCommand("insertText", false, text);
This basically inserts text
in the currently focused input in the current caret position (that's why you don't pass the input as a parameter). And, of course, this function updates the history accordingly.
If I wanted, I could coordinate every insert (like the **
mentioned in the question) in such a way that everything would be in the history. However, that would be too complicated because each markdown command has a different behavior. It would be too laborious.
Solution:
The following code has to be on componentDidUpdate
, and should only be executed after the text is changed programatically:
// In order to minimize the history problem with inputs, we're doing some tricks:
// - Set focus on the textarea
// - Set the value back to its previous value.
// - Select the whole text (that's the problem)
// - Insert the new value
this.refs.textarea.focus();
this.refs.textarea.value = previousText;
setSelection(this.refs.textarea, 0, previousText.length);
document.execCommand("insertText", false, text);
Effect
The Ctrl + Z works perfectly, but if you keep going back until the time the input was changed programatically, it will select the whole text. I mean, the history is preserved but at the cost of messing up with the selection if you go back enough. I believe it's good enough, better than re-implementing the input history.
Demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With