I am trying to implement a functionality that will let me drag around decorated text within a Draft.js editor and have spent a couple of days worth of brain power on this problem.
The blue hightlights are chords in lyrics and my goal is to adjust their position within the text.
onClick
when the decorator is clickedI am aware that I am creating a race condition in Draft.js but I do not know how to solve the problem.
I have a test set up which is available on Github.
https://github.com/tobi-or-not/draft-js-experiments
I click a button in the same component that displays the editor. This works perfectly. After the button is pressed, part of the text is marked
I click the decorator. After the click, the editor is back to it's initial state
There must be something I do not understand. Maybe there is a better way to implement this kind of drag-and-drop to begin with. Ideas and hints are much appreciated!
I stumbled upon a comment on the Draft.js Slack that pointed me in the right direction.
You only pass the decorator to initial state, but:
- The decorator has closure to the Button component (in the FIRST rendered instance, not current instance)
- Button component has closure to clickFn (in the same FIRST rendered instance)
- clickFn has closure to editorState (guess what ... in the same FIRST rendered instance)
Therefore your clickFn always updates the original state, not the current state Mindfuck, isn't it? You would basically have to update the decorator with each update to keep things linked properly to previous state. This is all caused by the fact that DraftJS EditorState is not just data object, but includes side-effects through the decorator.
The easiest way out of this is probably to use good old class components, so that the closures keep pointing to the same object, not a new one everytime.
And that's what I did. The component that contains the Draft.js editor is now a class component. The code is available on GitHub.