dalyIsaac / onenote-markdown

https://onenote-markdown.azurewebsites.net/
MIT License
43 stars 2 forks source link

Reduce the amount of re-rendering done by React #64

Open dalyIsaac opened 5 years ago

dalyIsaac commented 5 years ago

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, the Selection API is manually updated. However, during the process of Selection 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:

  1. If you put 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:

dalyIsaac commented 5 years ago

Update

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

dalyIsaac commented 5 years ago

As of 202b3b51b1704a60d37493fbc78f62427fb523c5, the rendering has reached feature-parity with the React versions (branches features/#64 and features/#48).

TODO:

For rerendering, refer to https://github.com/dalyIsaac/onenote-markdown/issues/65#issuecomment-508970477

dalyIsaac commented 4 years ago

Open to track above todos