Open dalyIsaac opened 5 years ago
Due to the difficulties with battling React, the aforementioned proposed solution is being put on hold. The current alternative is to create manually modify the DOM inside a Web Component. This avoids the issues of syncing the DOM and Virtual DOM, and the issue of React continually re-rendering elements.
https://github.com/dalyIsaac/onenote-markdown/tree/features/%2364-web-components
As of 202b3b51b1704a60d37493fbc78f62427fb523c5, the rendering has reached feature-parity with the React versions (branches features/#64 and features/#48).
TODO:
htmlEditor.ts
- Fixed in cb56a18155e1a1035c78f01fabffe88a18ac901aFor rerendering, refer to https://github.com/dalyIsaac/onenote-markdown/issues/65#issuecomment-508970477
Open to track above todos
Problem
At the moment, inputting new content into the editor causes a complete recompilation of OneNote HTML and Markdown. During the process of recompilation,
React.createElement
is used to create new React elements. However, this causes the virtual DOM to re-render the text node, which results in the position of the caret being lost. Currently, theSelection
API is manually updated. However, during the process ofSelection
being updated, either:Additionally, the caret noticeably strafes between the start of the OneNote Markdown and the expected caret location.
Proposed Solution
The proposed solution is to implement something like https://github.com/lovasoa/react-contenteditable (which is in turn based on https://stackoverflow.com/questions/22677931/react-js-onchange-event-for-contenteditable/27255103#27255103). This works by:
shouldComponentUpdate
to avoid caret jumps, then the contenteditable never rerenders (at least on keystrokes)2) If the component never re-renders on key stroke, then React keeps an outdated virtual DOM for this contenteditable.
3) If React keeps an outdated version of the contenteditable in its virtual DOM tree, then if you try to reset the contenteditable to the value outdated in the virtual DOM, then during the virtual DOM diff, React will compute that there are no changes to apply to the DOM!
(Courtesy of https://stackoverflow.com/questions/22677931/react-js-onchange-event-for-contenteditable/27255103#27255103).
The nature of the proposed solution means that each
StructureNode
should only be recompiled when an update occurs it specifically. This will prevent the entire OneNote Markdown from being re-rendered, improving performance.Notes
The following should be investigated:
shouldComponentUpdate
behavior? (see https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-shouldcomponentupdate)