newby alert
I am trying to use a contenteditable div in a react component hierarchy. I am hoping to use reflux instead of flux as I like the way one sets up actions and stores better in reflux (much less boilerplate, more features).
However, I am having an issue with contenteditable divs with an onInput handler attached. I'd like to keep my store up to date, so any onInput that occurs sends an action to the store, updating a field storing what is in the contenteditable div.
See the following gist, https://gist.github.com/dcnieho/0525f1becf1838616f5d, where test.js has three different ways to use an external store, changes to which lead to a setState at the top component, and this state gets passed down as props.
Using modes 1 and 3 (flux, or very simple handrolled version), things work fine: when i bash keys as fast as i can, the caret stays where it should be. When using mode 2 (reflux), the caret position will jump to the beginning of the content editable div every now and then. What i see in the log generated by my code is that the props coming in are behind the DOM content as accessed by the innerHTML
through a react ref. That triggers a rerender of the contenteditable div, changing its innerHTML.
Note that things work fine with flux even when commenting out the shouldComponentUpdate
function at line 92 and the componentDidUpdate
at line 105, which were styled after this answer. The same problem occurs when these are commented out in mode 2, reflux.
It thus appears that rerendering per se is not an issue (else all methods would have a problem when commenting out shouldComponentUpdate
), but rerendering and putting a different innerHTML
that what is at that moment in the DOM into the contenteditable div messes things up.
One further insight into this is the following. I log messages to the console indicating when things of interest happen. With vanilla flux, bashing keys, I get a nice chain of onInput being called, dispatcher called, render train, next onInput called. With reflux, i may get onInputs anywhere, before render train is finished, or even before the dispatcher (well, action/store its called in reflux) is called for the previous onInput. It seems like some things happen asynchronously in reflux where they shouldn't for my use case?
Am I doing something wrong? Is the way in which event happen in reflux not suitable for what i want? Is there a better way to approach content editable divs in react+flux? Are there important concept I seem not to understand (I am a newbie)?